# How the Blob Artifact System Handles Large Object Storage in Oh‑My‑Pi (OMP)

> Discover how Oh My Pi's blob artifact system stores large objects efficiently. It uses SHA256 content addressing and blob references to reduce session file size and enable deduplication.

- Repository: [Can Bölük/oh-my-pi](https://github.com/can1357/oh-my-pi)
- Tags: internals
- Published: 2026-05-21

---

**The blob artifact system externalizes large binary payloads into a content‑addressed SHA‑256 store, replacing base64 data with compact `blob:sha256:` references to keep session JSONL files small and enable automatic cross‑session deduplication.**

The `omp` (Oh‑My‑Pi) coding agent manages conversation sessions as JSONL files that can grow unwieldy when image data is embedded as base64 strings. According to the source code in `can1357/oh-my-pi`, the blob artifact system solves this by moving payloads exceeding **1024 bytes** into a global, immutable blob store while preserving lightweight references in the session log.

## Content‑Addressed Storage Architecture

### SHA‑256 Hashing and File Layout

At the core of the system is `BlobStore`, implemented in [`packages/coding-agent/src/session/blob-store.ts`](https://github.com/can1357/oh-my-pi/blob/main/packages/coding-agent/src/session/blob-store.ts). When writing data, `BlobStore.put` (or its synchronous variant `putSync`) computes a **SHA‑256 hash** over the raw bytes and writes the content to `<blobsDir>/<hash>`. The method returns a structured reference string in the format `blob:sha256:<hex‑hash>`.

```typescript
import { BlobStore } from "@oh-my-pi/pi-utils";

const store = new BlobStore("/home/user/.omp/agent/blobs");
const result = store.putSync(Buffer.from(bigBinary));

console.log(result.ref); // → "blob:sha256:9f2d..."

```

Because the filename is deterministically derived from content, identical binaries automatically map to the same filesystem location, guaranteeing **deduplication** without additional indexing.

### Global Storage Directory

Blobs reside in a **global directory** (`~/.omp/agent/blobs/` by default) that is shared among all sessions. As configured in `SessionManager`, the `BlobStore` instance uses `getBlobsDir()` to locate this path, meaning no per‑session copies are created when forking or resuming conversations.

## Externalization Workflow During Persistence

### Threshold Detection

When persisting a session entry, `SessionManager.prepareEntryForPersistence` scans the message’s `content` array for image blocks. The system triggers externalization when:

- The block’s `data` string is a base64 image **≥ 1024 bytes** (`BLOB_EXTERNALIZE_THRESHOLD`)
- The block contains a provider `image_url` using a `data:image/...;base64,` data‑URL

These checks occur in [`packages/coding-agent/src/session/session-manager.ts`](https://github.com/can1357/oh-my-pi/blob/main/packages/coding-agent/src/session/session-manager.ts) around lines 77‑92.

### Blob Storage and Reference Replacement

Once triggered, the payload is handed to `BlobStore.put`. The original base64 string or data‑URL is then **rewritten** to the `blob:sha256:<hash>` reference before the entry is appended to the JSONL file. This keeps each session line compact while maintaining a stable, content‑addressed identifier.

```typescript
import { externalizeImageData } from "@oh-my-pi/pi-utils";

// Inside prepareEntryForPersistence
if (msg.content?.[i]?.type === "image") {
  const data = msg.content[i].data; // base64 string
  const ref = await externalizeImageData(blobStore, data);
  msg.content[i].data = ref;        // replace with blob:sha256:…
}

```

## Rehydration on Session Load

### Resolving Blob References

When loading a session, `SessionManager.resolveBlobRefsInEntries` scans entries for strings prefixed with `blob:`. For each match, it extracts the hash and calls `BlobStore.get(hash)` to retrieve the stored bytes from [`packages/coding-agent/src/session/blob-store.ts`](https://github.com/can1357/oh-my-pi/blob/main/packages/coding-agent/src/session/blob-store.ts).

### Data Reconstruction

The system handles two reconstruction paths:

- **Image blocks**: Raw bytes are re‑encoded to base64 for the consumer
- **Data‑URLs**: Bytes are returned as the original UTF‑8 string

If the blob file is missing, `omp` logs a warning and leaves the reference untouched, preventing a hard crash while preserving data integrity.

```typescript
import { resolveImageData } from "@oh-my-pi/pi-utils";

const data = entry.content[i].data; // may be blob ref
const base64 = await resolveImageData(blobStore, data);

// base64 now contains the original image data (or original ref if missing)
entry.content[i].data = base64;

```

## Deduplication and Immutability Guarantees

The use of content addressing provides several operational benefits:

- **Write idempotency**: Calling `put` or `putSync` multiple times with identical data results in the same hash and filename, making the operation safe to repeat
- **Cross‑session sharing**: Because blobs are stored globally, different sessions that process the same image (e.g., a common screenshot) reference the same physical file
- **Immutability**: Once written to `<blobsDir>/<hash>`, blob files are never modified; new content receives a new hash, ensuring historical session files remain valid

## Summary

- **Content addressing**: SHA‑256 hashes identify blobs stored as flat files in `~/.omp/agent/blobs/`
- **Externalization threshold**: Base64 payloads ≥ 1024 bytes or data‑URLs are moved to the blob store
- **Reference format**: Session files contain `blob:sha256:<hash>` instead of raw binary data
- **Rehydration**: `BlobStore.get` retrieves bytes on load, converting back to base64 or UTF‑8 as needed
- **Global deduplication**: Identical content across sessions maps to a single physical file

## Frequently Asked Questions

### What is the size threshold for blob externalization in Oh‑My‑Pi?

The `BLOB_EXTERNALIZE_THRESHOLD` constant is set to **1024 bytes** according to [`docs/blob-artifact-architecture.md`](https://github.com/can1357/oh-my-pi/blob/main/docs/blob-artifact-architecture.md). Any base64 image data or data‑URL exceeding this length is automatically externalized to the blob store during the `prepareEntryForPersistence` phase.

### How are blob references formatted inside session JSONL files?

Persisted references use the literal string format `blob:sha256:<hex‑hash>` (for example, `blob:sha256:9f2d4c…`). These references are resolved internally by `SessionManager` and are not treated as URLs by the application router.

### Where does Oh‑My‑Pi physically store blob artifacts?

Blobs are stored in a **global directory** defaulting to `~/.omp/agent/blobs/`. The path is determined by `getBlobsDir()` and shared across all sessions, enabling deduplication when the same binary content appears in different conversation histories.

### What happens if a session references a blob that no longer exists on disk?

If `BlobStore.get` fails to locate the file for a referenced hash, the system logs a warning and returns the original `blob:sha256:` reference string unchanged. This graceful degradation prevents session loading from crashing while alerting the user to the missing artifact.