Skip to main content
Glama

codex-session-gc

Browse Codex storage, select stopped work and delete an exact set of histories while unrelated sessions continue running. The terminal interface uses Textual; CLI and MCP operations share its selection rules. MAIN histories can be selected. Explicit Guardian histories can also be selected. Their historical parent association does not select or require deletion of the parent. Age is a caller-supplied filter, not a fixed retention policy.

What is new in 0.5.1

The installer avoids false storage refusals on affected filesystems while dependencies create and rename temporary directories. It checks the free-space floor during each subprocess and cumulative installation growth at subprocess boundaries.

Related MCP server: mcp-compact

What was new in 0.5.0

A matched installer stages releases alongside older consumers and reports an explicit MCP command. The cleanup contract recognizes attached histories, the state schema at migration 62, and stopped work whose spawn relationship still records Open. Doctor and MCP can compare an explicitly imported source-support record with the current helper and profile; that record does not authorize cleanup. The terminal keeps essential controls visible while its content scrolls in compact windows.

Download and install

The 0.5.1 installation workflow uses a matched Linux x86_64 bundle and a standard-library installer. Obtain the published assets and independently verify their attestations before using them. Python 3.14 or newer, uv and a separately trusted GitHub CLI (gh) are prerequisites. The qualified deployment is Ubuntu 26.04 LTS, glibc 2.43; other environments require qualification. The native contract uses wire 6, the exact state schema and migration 62, and the specified companion schemas.

Obtain the full 40-character assembly source commit independently from a trusted release record. Use a trusted gh whose attestation verify --help includes --repo, --signer-workflow, --source-digest, --source-ref, --predicate-type, --deny-self-hosted-runners and --format. Verify the bootstrap before executing it; an unverified installer cannot verify itself:

set -eu
mkdir codex-session-gc-download
cd codex-session-gc-download
curl --fail --location --output codex-session-gc-installer-0.5.1.pyz \
  https://github.com/YuriyKrasilnikov/codex-session-gc/releases/download/v0.5.1/codex-session-gc-installer-0.5.1.pyz
GC_ASSEMBLY_COMMIT=FULL_40_CHARACTER_ASSEMBLY_COMMIT
gh attestation verify codex-session-gc-installer-0.5.1.pyz \
  --repo YuriyKrasilnikov/codex-session-gc \
  --signer-workflow YuriyKrasilnikov/codex-session-gc/.github/workflows/artifacts.yml \
  --source-digest "$GC_ASSEMBLY_COMMIT" --source-ref refs/heads/main \
  --predicate-type https://slsa.dev/provenance/v1 --deny-self-hosted-runners \
  --format json

The verifier checks the downloaded file as the attestation subject. Stop on any verification failure; do not execute the bootstrap. The attestation establishes assembly origin, not cleanup correctness or a native rebuild. The exact source commit is an input to verification, not a value inferred from the downloaded file.

Stage the release using separately trusted absolute executable paths. The command prints an installation ID; retain that exact ID for activation and recovery. Substitute your actual existing Codex home and receipt directory:

python3.14 -I codex-session-gc-installer-0.5.1.pyz --release v0.5.1 \
  --action stage --gh /absolute/path/to/gh --uv /absolute/path/to/uv \
  --python /absolute/path/to/python3.14
python3.14 -I codex-session-gc-installer-0.5.1.pyz --action activate \
  --installation-id INSTALLATION_UUID --home /absolute/codex-home \
  --receipt-dir /absolute/receipt-directory
python3.14 -I codex-session-gc-installer-0.5.1.pyz --action status \
  --installation-id INSTALLATION_UUID

Activation reports the exact mcp_argv for registering the server. Status can identify a completed staged installation without an activation intent; activate that same ID explicitly. For an existing activation intent, --action reconcile --installation-id INSTALLATION_UUID records an observable terminal state without repeating the switch. An unknown switch remains unknown; reconciliation does not resume installation or retry it. Use the same installation directory. The installer verifies the downloaded bundle before consuming it and does not modify Codex configuration. A missing or insufficient verifier causes refusal. The installer and its local executables must be trusted independently. Installation requires network access and does not require a Rust toolchain.

For an existing installation, retain old receipt consumers and follow recovery and upgrades. Consumers of the 0.4.0 release must retain it while their unresolved receipts require it. A version directory already present in an application directory is not replaced. To install another copy of 0.5.1, choose both a fresh --install-dir and a fresh --bin-dir; use the resulting absolute CLI and reported MCP command. This does not switch a launcher in the old application directory. The same-version 0.5.0 example in recovery and upgrades illustrates this procedure.

Source checkout

git clone https://github.com/YuriyKrasilnikov/codex-session-gc.git
cd codex-session-gc
uv sync --locked

Run .venv/bin/python -m codex_session_gc in place of codex-session-gc below. For cleanup, download and retain the qualified helper from the matching release bundle, then pass its absolute path with --helper. A source rebuild with a different binary digest requires separate qualification and a new matched release; it is not an installation shortcut. See native reconstruction and package assembly, architecture and Codex updates.

License

The project is licensed under Apache-2.0. NOTICE retains upstream attribution. The third_party directory contains dependency notices and their source index; these accompany source packages, wheels and release bundles.

Diagnose compatibility

Observe the installed profile, supplied helper and exact database schemas before investigating a Codex update:

codex-session-gc doctor --home /absolute/codex-home --helper /absolute/release/codex-session-gc-native
codex-session-gc doctor --home /absolute/codex-home --helper /absolute/release/codex-session-gc-native --json

The report shows the raw installed profile SHA-256, source identity, expected and observed helper digests, and each declared database's schema/migration result. An absent optional database differs from a missing authoritative state database, a mismatch, or an unavailable observation. Exit status is 0 when the supplied helper and present databases match, 1 for a known mismatch or missing state, and 3 for incomplete observations without a known mismatch. Omitting --helper leaves that observation unknown. --max-read-bytes and --timeout-seconds control observation bounds using the existing execution defaults.

Doctor does not change user tables or histories, copy storage, create cleanup receipts, launch the helper, or acquire application maintenance/writer ownership. Ordinary SQLite read transactions can create or update WAL/SHM coordination files and use SQLite locks. Results are separate observations, not a global snapshot or permission to delete; execution still requires native ownership and fresh checks. The source-support claim is separate from these local observations. Producer identity supplied on the command line remains an unverified caller observation; an unknown running binary origin is not inferred from a version string. By default, doctor observes the bundled support record. After an explicit support import, use the returned record and context digests to compare that record against the current profile and helper:

codex-session-gc doctor --home /absolute/codex-home \
  --helper /absolute/release/codex-session-gc-native \
  --support-install-dir /absolute/application-directory \
  --support-installation-id INSTALLATION_UUID \
  --support-record-sha256 RECORD_SHA256 --support-context-sha256 CONTEXT_SHA256 --json

All four support options are required together. A missing or changed selection is reported unavailable; doctor does not substitute the bundled record. The saved receipt records a past verification and is not fresh authentication or cleanup authority. Local profile, helper and database observations stay separate. See compatibility for the supported boundary.

Browse and select

The browser opens with the largest work groups first. Works mode keeps expandable context; Histories mode ranks matching histories across all works in a flat list. Choose the ordering field and ascending or descending direction. Reordering keeps selected IDs unchanged and never selects contextual parents. Each group shows its own stored bytes, agent bytes and total across distinct physical histories, including plain and Zstandard representations and pre/post-revert rollouts. Known observed bytes are kept separately from an exact total: an incomplete observation shows ≥known and an unknown total. Sorting ranks the known observed amount; it does not claim to order unknown actual totals. Equal known amounts put exact totals before incomplete totals, then use the stable session ID. Wholly unknown amounts stay last in both directions; exact zero is a value. Activity ordering also keeps missing dates last. These are stored lengths, not promised recovered disk space. Shared providers and conditional reclaim remain unknown until the complete cleanup preview. MAIN, ordinary agent, Guardian and unknown source labels come from stored source metadata; a missing parent does not make a history MAIN.

Filter by text, exact stored directory, archive state, last activity, stored-byte bounds, history type and work group. Directory choices compare stored cwd strings literally and case-sensitively, including punctuation and brackets; paths are not resolved or normalized. Agents (all) includes ordinary agents and Guardians; separate choices narrow to either source classification. A minimum byte bound can be proved by the known lower bound; a maximum requires an exact total. Both bounds apply together. Sort by total size, own size, agent size or activity. The date matches each history whose known last activity is strictly earlier than the selected UTC instant. Group activity is shown separately. The initial date is visible and editable; it does not select anything automatically.

Enter expands a group. Space toggles the focused matching history; Select matches selects matching histories without selecting a contextual parent automatically. Changing filters preserves selected IDs. Refresh cannot add deletion IDs.

Preview reads scoped SQL metadata and bounded metadata headers across the managed physical namespace, including orphan consumers. It does not copy databases or read complete history bodies. Review the exact IDs, cutoff, sizes and retention reasons. Type literal DELETE to dispatch once. Native ownership, history-provider and current-state checks may still refuse or narrow the conditional selection. A catalogue lifecycle label is not proof of closure.

Esc or Cancel stops and reaps the preview worker before dispatch. After dispatch, the interface joins the owned execution and preserves its result and receipt. For partial or unknown results, keep the receipt and reconcile; do not repeat the original delete command merely because its reply was lost.

During execution, the terminal browser shows the operation UUID, elapsed waiting time, the current root when known and returned root outcomes. Returned outcomes may include refusal, partial or unknown results; they do not promise reclaimed space. Native silence remains waiting. Progress is transient, so keep the receipt for recovery even if the display closes.

ui --cutoff sets the visible initial UTC boundary. --receipt-dir chooses the durable receipt directory, which must be outside the selected Codex home. Its default is the user's state directory. The UI requires an interactive terminal.

CLI preview and cleanup

Choose a stopped session root and an explicit UTC cutoff:

codex-session-gc plan --online --home /absolute/codex-home \
  --cutoff 2026-08-01T00:00:00Z --closed-work PARENT_UUID --json

The date above is an example. Repeat --closed-work for independent roots. By default the requested set includes each root and its spawned descendants. Repeat --select-thread UUID to request only particular histories instead:

codex-session-gc apply --online --home /absolute/codex-home \
  --cutoff 2026-08-01T00:00:00Z --closed-work PARENT_UUID \
  --select-thread CHILD_UUID --helper /absolute/codex-session-gc-native \
  --receipt /absolute/new-cleanup.sqlite --json

Omitting --select-thread considers the selected work's whole membership against the cutoff and retention rules. The cutoff narrows deletion eligibility, not the ownership scope. Retained descendants prevent selecting their cascading parent. Unknown origin, age, archive state, missing history and ambiguous topology remain visible as retention or refusal. Known MAIN and archive states are not automatic policy exclusions; the native contract determines supported effects.

Preview JSON contains roots, selected, conditional deletions, corresponding sizes in stored bytes, retained reasons and errors. physical_manifest binds every selected owner's actual representation, immutable rollout ID, path, stat, header digest and independent history/fork metadata. shared_retained_bytes counts distinct transitive providers outside the selected physical set; conditional_reclaim_bytes is the selected stored total, not guaranteed disk reclaim. incomingReferencesComplete records complete observed provider headers; closureCertified remains false. These observations are not an atomic snapshot or a certificate that writers have released ownership. Preview is read-only and non-executable. Apply takes fresh observations; it does not execute a saved preview file. Guardian previews identify their historical parent association. UI confirmation and MCP declarations bind that association; a changed association is refused before dispatch. Direct CLI apply derives fresh facts.

Apply reports every requested root, selected subset, retained reason and native outcome, including work never dispatched. Confirmed eligible work alongside a skipped root produces a partial aggregate. When no selected history is eligible, no helper or receipt is created. --default-provider defaults to openai; individual stored providers are checked separately.

Results after interruption

Use only the saved receipt:

codex-session-gc reconcile --online --receipt /absolute/cleanup.sqlite --json

Reconcile accepts no home, helper or selection override. It never sends another deletion request or continues work that was not dispatched. Its scope is saved_journal_units; roots skipped before receipt creation are outside that scope. Original delivery outcomes and observed final states remain distinct.

Completed current-format journal records can be displayed using their saved metadata even after the qualified helper changes. A fresh observation of an unresolved request requires the exact current profile and wire format. Retired profiles and journal schemas are not converted or tried automatically. CONFIRMED_FINAL_STATE means the selected effects were observed absent within the declared bound; it does not attribute every effect to a particular invocation or measure reclaimed space.

Plan exits 0 for an available conditional selection and 3 for unavailable facts or an invalid selection. Apply and reconcile exit 0 for confirmed, 3 for refused, and 4 for partial or unknown. Invalid arguments exit 2.

Storage and resource contract

Catalogue reads metadata in a short read-only live-WAL transaction, closes it, then walks active/archive names and obtains stat identities through safe directory descriptors. Each catalogue observation owns one pool of at most eight workers. Workers obtain full nofollow metadata through borrowed parent descriptors, in chunks of at most 16 sibling names. At most eight chunks are outstanding; results are reduced in enumeration order. Each batch settles before recursion or parent descriptor closure, and the pool is joined before observation returns. Catalogue teardown waits for this work. A blocked filesystem call has no finite completion guarantee. Catalogue never opens history content. Filename ownership and immutable rollout identity distinguish reverted histories and competing copies; ambiguous objects are attributed to no owner's known subtotal. Missing namespace coverage retains known lower bounds without inventing an exact total. SQL history mode is reported as SQL metadata; physical lineage remains explicitly unknown. Filtering, grouping and paging use detached metadata. Independent databases do not form one global concurrent snapshot. Path checks reject observed invalid paths and changed endpoint identities; they do not establish uninterrupted namespace ownership.

Preparation reads scoped metadata, selected effect keys and bounded first-line physical headers. Native execution holds maintenance and writer/lifecycle ownership of the whole root and all actual spawn descendants, including unselected siblings. A busy member refuses that work before effects. Under retained ownership and transactions, it checks the complete closure, walks bounded namespace headers to protect retained providers, and revalidates schema, identities and exact SQL effects. A spawn edge marked Open or Closed is relationship metadata, not evidence of inactivity; a status-only change does not itself refuse cleanup. Unknown status or an ambiguous parent refuses. Related selected-thread metadata updates and dependency-reference publication (for example, a new fork history reference) must finish before cleanup; acquiring a writer guard does not independently certify their completion. Selected descriptors remain open for the checks immediately before unlink. History bodies are not scanned or hashed.

The supported native contract is wire 6 and the exact bundled state schema through migration 62, with the qualified companion database schemas. The same qualified path supports plain JSONL and Zstandard, legacy and paginated history, and every observed pre/post-revert rollout belonging to a selected owner. Historical physical metadata may differ from the current SQL provider or role; the current header must agree with current SQL. Unsupported schema identities, old wire versions and ambiguous competing representations refuse. A selected Guardian requires matching SQL/header source identity, a valid historical parent association and no incoming spawn edge. Its associated parent need not exist or be closed; selecting that parent never implicitly selects the Guardian. Exact selected-owner rows in guardian_review_feedback and thread_read_receipts are deleted for both ordinary and Guardian histories; unselected opaque rows remain untouched. Matched retained Guardians keep their existing physical writer guards. The runtime boundary is the qualified local stock Codex 0.166.0 persistent public CLI and app-server workflows, with MAv1 and MAv2 qualified separately. Custom internal controllers and arbitrary direct ephemeral-library access are outside this boundary. It is not a guarantee of business success or an empty runtime heap.

--max-read-bytes defaults to 256 GiB and --timeout-seconds to six hours per collection or dispatch. These are cooperative limits, not memory reservations or kernel completion guarantees. Database and selected rollout extents are admission bounds; unrelated and retained body lengths do not become global rollout-size limits. SQLite page reads use a cooperative deadline rather than exact I/O accounting. Requests are limited to 16 MiB, first-line metadata to 1 MiB including its newline, and combined native output to 1 MiB. Bounds do not expand automatically.

The separately built helper uses Rust 1.99.1 and Edition 2024. See native build instructions. A new binary requires qualification and a matching bundled identity; an arbitrary successful build is not accepted.

MCP

The stdio server exposes compatibility_status, query_catalogue, session_details, prepare_cleanup, apply_cleanup, cleanup_status and reconcile_cleanup. Register it with absolute paths:

Use the exact mcp_argv returned by activation when registering the server with codex mcp add. It binds the installed release, chosen home, receipt location, application directory and installation ID; registration changes the client configuration. compatibility_status uses bundled support when called without arguments. To compare an imported record, pass both record_sha256 and context_sha256 to that tool. It reads within the startup installation scope; clients cannot choose a filesystem path or a different installation. Selecting another imported record takes effect on the next call without restarting.

For observation only, add --read-only to the server arguments. This mode exposes compatibility_status, query_catalogue, session_details, prepare_cleanup and cleanup_status. Preparation returns a conditional report with can_apply_via_mcp=false and creates no cleanup operation UUID, declaration or receipt. It needs no helper. Apply and reconciliation tools are unavailable because both can write application data or receipt evidence. Default mode retains the confirmed apply and reconciliation tools. Read-only describes application data and receipt evidence; SQLite read coordination may still use locks or sidecars.

Choose the home used by Codex when activating the installation. Starting the server itself does not edit client configuration. Reconnect the client to load changed server code. Ask for the largest project groups, agents last active before a chosen date, or a preview for explicit IDs. Query and details share a cached catalogue identity; explicit refresh replaces it. query_catalogue accepts cwd for exact stored-directory equality and archive_state values archived, not_archived or unknown. Its scope values ordinary_agents and guardians narrow the existing combined agents scope. These predicates combine with text, date, size and work filters on detached metadata. order_target=work accepts sort values total, own, agents or activity; order_target=history accepts stored_bytes or activity. direction is asc or desc. The default is work/total/desc; invalid combinations are refused. For the largest matching agents across works, use scope=agents, order_target=history, sort=stored_bytes, direction=desc. For the oldest matching histories in one work, combine its roots filter with history/activity/asc. The response echoes order with target, field and direction. Filtering and ordering cover the full matching history sequence before pagination; total_matches, offsets and limits count histories in either mode. Contextual parents remain in group summaries and are not matching histories unless their own facts match. Changing filters does not reread storage. Preparation reads fresh scoped facts and returns a conditional report without a journal or deletion. Pages contain at most 100 histories; preparation accepts at most 200 distinct IDs per request. Larger selections can use the terminal UI.

Review the complete preparation report, then explicitly call apply_cleanup with the unchanged string fields from confirmation: operation_id and digest. The server retains the exact reviewed roots and candidate IDs, cutoff, startup home identity, Guardian associations, physical manifest and qualified profile. The client does not return filesystem integers or reconstruct the declaration. An unclaimed confirmation expires when the server restarts; applying it then returns unknown without dispatch. A matching saved receipt is observed only. Catalogue JSON uses stored_bytes for an exact total or null, known_stored_bytes for the observed lower bound, physical_rollouts for attributed objects and physical_complete for complete membership. Work groups expose corresponding own/agent/total known and exact stored-byte values plus incomplete-history counts. Initial physical_lineage is unknown; shared-retained and conditional-reclaim values are null until preparation. The digest binds those inputs; it does not establish human consent. The helper and receipt directory are fixed at server startup and cannot be chosen by tools. The receipt directory must be outside the selected home. Without --helper, the server discovers the qualified helper using the same rules as Textual.

Keep the operation UUID after cancellation, disconnect or a lost response. Read cleanup_status or call reconcile_cleanup with that UUID. Reconciliation may write observation evidence to the existing receipt and never dispatches deletion. A duplicate apply observes the saved attempt; a different digest for a prepared or saved operation is refused. A completed refusal before receipt creation remains visible to apply and status in that server process. After restart, missing or unreadable receipts mean unknown, including when an older call may still be preparing. Do not create a replacement operation to retry an unknown deletion. Transport cancellation waits for owned backend cleanup; receipts retain explicit unresolved lifecycle state when cleanup is unproven.

Metadata and AI clients

Tools return metadata such as session titles, stored working directories, IDs, timestamps, sizes, source/parent relationships and diagnostics. MCP sends these results to its client; an AI client may include them in requests to its configured model provider. Read-only mode limits mutations and does not redact metadata. Do not publish raw cleanup receipts or conversation transcripts in public issues or releases. Share only the minimal redacted diagnostic information needed.

Related MCP Connectors

Related MCP Servers

  • F
    license
    Not graded
    quality
    B
    maintenance
    Enables agents to analyze their session context usage and surgically remove heavy or unnecessary events from their history, preserving coherent transcripts and freeing token budget without restarting.
    -
  • A
    license
    Not graded
    quality
    B
    maintenance
    Enables reading and reconstructing local Codex session history through MCP, with verified session resolution, paginated recovery, project discovery, and multi-root project scopes.
    MIT