Metadata-Version: 2.4
Name: sessionfold
Version: 0.1.0a4
Summary: Free disk space by storing repeated screenshots in Codex histories only once
Author: Shivam Kumar
License-Expression: Apache-2.0
Project-URL: Homepage, https://github.com/shivampkumar/sessionfold
Project-URL: Repository, https://github.com/shivampkumar/sessionfold
Project-URL: Issues, https://github.com/shivampkumar/sessionfold/issues
Project-URL: Changelog, https://github.com/shivampkumar/sessionfold/blob/main/CHANGELOG.md
Keywords: codex,agents,sessions,deduplication
Classifier: Development Status :: 3 - Alpha
Classifier: Environment :: Console
Classifier: Operating System :: MacOS
Classifier: Operating System :: POSIX :: Linux
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Topic :: System :: Archiving
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Dynamic: license-file

# Sessionfold

Sessionfold is a local-first disk safety tool for Codex histories. It finds
oversized JSONL sessions and creates lossless, content-addressed archives in
which identical inline images are stored once across every archived session.

**The current alpha supports Codex only. It does not support Claude Code.**
Claude Code normally stores image blocks in a different JSON representation,
which Sessionfold does not currently deduplicate.

It does not upload telemetry or session data, display conversation content, or
modify an active transcript. Scanning is read-only. Source removal is optional
and occurs only after a full byte-exact reconstruction has been verified.

## Important: this is cold storage

Sessionfold is not transparent compression inside Codex.

- `archive` leaves the original JSONL untouched, so the chat remains available
  in Codex. This creates the verified cold-storage copy but does not reclaim the
  original file's bytes.
- `reclaim` removes that original JSONL after verification. This recovers disk
  space, but the chat may disappear from Codex and may not be resumable there.
- `restore` recreates the original JSONL byte for byte. Sessionfold verifies the
  restored file, but automatic reintegration into the Codex sidebar has not yet
  been validated.

If every chat must remain immediately usable in Codex, use `scan`, `archive`,
and `verify`, then stop before `reclaim`.

## Why I built it

I bought a 1 TB Mac, and about 20 days later it had 80 MB of free space left. I
assumed the healthcare datasets I had been working with were responsible. After
some debugging, my agent reported:

> The main culprit is not the healthcare data: `~/.codex/sessions` is about 566
> GiB, mostly individual rollout JSONL files of roughly 5 to 6 GiB each from
> September 3 to 5.

My reaction was basically, "what the shit?"

Those histories contained screenshots copied into JSONL as base64. Compaction
and related sessions had repeated many of the same images thousands of times.
I wanted the disk space back without blindly deleting my work or trusting a
lossy cleanup script. That became Sessionfold.

At 80 MB free, the machine was already too full to build a safe archive on the
same disk. I first freed some breathing room. If your internal drive is that
close to full, use `--store` to put the archive on an external volume.

## Why it exists

Screenshot-heavy agent sessions can embed base64 images directly in JSONL.
Compaction and forks may repeat the same image thousands of times. Ordinary
gzip cannot efficiently deduplicate copies that are far apart or in different
files.

Sessionfold provides five operations:

- `scan` inventories histories; `--deep` hashes inline images and estimates
  duplicate bytes without decoding or displaying them.
- `archive` writes non-image transcript bytes to a compressed thin stream and
  stores images in a global SHA-256 content-addressed store.
- `verify` reconstructs and hashes the full logical transcript without writing
  a source-size temporary file.
- `reclaim` verifies the archive and original again, then removes only the exact
  source named in the manifest after explicit confirmation.
- `restore` recreates the original JSONL byte-for-byte at a new path.

## Install the alpha

Requires Python 3.10 or newer and has no runtime Python dependencies.

```bash
python3 -m pip install --pre sessionfold
sessionfold scan
```

The `--pre` flag is required while Sessionfold is published as an alpha.

To install from a checkout:

```bash
python3 -m pip install .
./bin/sessionfold scan
```

## Usage

```bash
sessionfold scan
sessionfold scan --deep --top 20
sessionfold archive /path/to/completed.jsonl
sessionfold list
sessionfold verify ~/.sessionfold/archives/ARCHIVE/manifest.json
sessionfold reclaim ~/.sessionfold/archives/ARCHIVE/manifest.json --yes
sessionfold restore ~/.sessionfold/archives/ARCHIVE/manifest.json --output ./restored.jsonl
```

The recommended workflow separates review from removal:

```bash
sessionfold archive /path/to/completed.jsonl
sessionfold verify ~/.sessionfold/archives/ARCHIVE/manifest.json
sessionfold reclaim ~/.sessionfold/archives/ARCHIVE/manifest.json --yes
```

For a one-command archive and removal, after reviewing the risks below:

```bash
sessionfold archive /path/to/completed.jsonl --remove-source
```

Both removal paths perform the same second archive reconstruction and source
hash check. They refuse recent files, files open by another process, changed
sources, and platforms where open-file detection is unavailable.
Removing a vendor transcript may hide that session from the product UI until
it is restored.

## Defaults and scope

- Codex discovery: `${CODEX_HOME:-~/.codex}/sessions`
- Archive store: `~/.sessionfold`
- Inline image candidates: 4 KiB to 64 MiB each

Creating an archive requires additional disk space before any source can be
removed. When the source disk is critically full, choose an external store:

```bash
sessionfold archive /path/to/completed.jsonl --store /Volumes/External/sessionfold
```

The initial archive format targets JSONL transcripts containing quoted
`data:image/*;base64,...` values. Unknown or small data URIs remain inline.
Transcript formats are vendor-owned and unstable, so compatibility must be
tested as they evolve. Sessionfold is archival storage and Codex does not read
its archive format directly. Codex is the only supported target in this alpha.
Do not use Sessionfold to reclaim Claude Code histories.

If an archive store is relocated, pass its new root with `--store` to `verify`
or `restore`.

## Limits worth knowing

- Sessionfold cold-archives completed histories. It does not rewrite or shrink
  the live history that Codex is currently using.
- The first archive needs enough temporary headroom for its thin stream and any
  image blobs not already in the store. Use an external `--store` when the
  internal disk is critically full.
- Archive data is not encrypted. Protect it like the original transcript.
- Source removal depends on reliable open-file detection. It fails closed when
  that check is unavailable. In this alpha, removal is not supported by default
  on Windows, although scan, archive, verify, and restore run in Windows CI.
- The safety checks assume an ordinary single-user machine, not a malicious
  local process deliberately racing filesystem operations.
- Codex owns its transcript format and can change it. Verify compatibility on
  synthetic data after major Codex updates before reclaiming original files.

## Safety and privacy

- no network access or telemetry;
- no prompt, image, or tool-output display;
- no implicit deletion or whole-root mutation;
- no edits to vendor databases or active transcripts;
- atomic archive directories and immutable, content-addressed blobs;
- source-size and SHA-256 validation of every logical reconstruction;
- blob size and SHA-256 checks before a restore is accepted;
- existing restore targets are never overwritten.

See [SECURITY.md](SECURITY.md) and [PRIVACY.md](PRIVACY.md).

## Optional Codex plugin

The repository includes a Codex plugin manifest and a safety-focused skill.

## Development

```bash
python3 -m unittest discover -s tests -v
python3 -m py_compile sessionfold/cli.py
python3 -m build
```

The feasibility measurements in `experiments/` are single-machine benchmarks,
not promises about every corpus.

See the [archive format](docs/archive-format.md),
[validation record](docs/validation.md), and
[competitive boundary](docs/competitive-landscape.md) for the current contract.
