Introduction

If you have run long sessions with DSH, you have likely encountered this issue: opening an old session causes a noticeable delay. The problem lies in the storage layer. DSH’s JSONL session backend compresses each batch of writes into a separate zstd frame before appending it to the file. A long session can easily accumulate tens of thousands of frames. During reading, every frame must be decompressed individually. Since the backend lacks seek-style reading for suffixes, retrieving data—whether just the tail or the entire file—requires decoding the whole file.

The number of frames is fixed by historical writes and cannot be reduced post-hoc. kkishapppy/dsh-session-repacker addresses this issue: it repacks scattered thousands of frame logs into the official native format. Actual tests show the maximum session opening time dropping from approximately 661ms to approximately 126ms.

What is it

dsh-session-repacker is a DSH plugin (MIT license, version 0.1.0) maintained by kkishapppy. It repacks the thousands of independent zstd frames generated by DSH’s JSONL session backend batch writes into the official native two-frame format: the header frame contains exactly one line of header, while the rest of the plaintext is concatenated and recompressed into a single event frame.

Two key points:

  1. The plaintext after repacking remains byte-for-byte unchanged. The DSH read path is fully compatible; the read-side assertZstdHeaderFrame only requires the first frame to be exactly one line of header, which the repacked result satisfies.
  2. The plugin only handles maintenance and does not alter any read APIs or data semantics. It covers all paths for reading old sessions from disk: GUI opening, new conversation continuation/branching, and sub-session inheritance.

Results

Actual test results provided by the author:

Item Before Repacking After Repacking
Max single session 14,467 frames / 5.49MB / ~661ms 2 frames / 2.09MB / ~126ms (~6x)
All 24 old sessions 39,911 frames / 20.08MB 48 frames / 10.67MB

In addition to opening speed, the compressed volume is also reduced by approximately half—the compression ratio of a single large frame is far superior to that of thousands of independent small frames.

Installation and Usage

Install as a DSH plugin (recommended):

dsh plugin --profile web add dsh-session-repacker

You can also clone it to the plugins/ directory and link it into your profile. If you wish to build it yourself, execute the following in the repository directory:

npm i
npx -y tsdown@0.22.2 --config ./tsdown.config.ts

The output artifact is lib/index.mjs.

To enable it, configure the plugin and parameters in profiles/<profile>/cordis.patch.yml:

- id: session-repacker
  config:
    root: 'E:\DeepSeekHarness\sessions'   # Session root directory (required)
    minFrames: 200        # Skip processing if frames are below this value (default 200)
    minAgeMs: 600000      # Skip processing if mtime is less than this many ms ago (default 10 minutes)
    intervalMs: 3600000   # Periodic maintenance interval in milliseconds (default 1 hour)

It takes effect after restarting the server: the plugin performs a full scan upon startup and then performs periodic maintenance based on intervalMs. root is the only required field; the other three have default values, so it can run without configuration.

Standalone CLI

If you don’t want to run background tasks by attaching a plugin, the repository provides a standalone CLI that does not require the DSH service:

node tools/repack.mjs <root>                  # Scan and repack
node tools/repack.mjs <root> --dry-run        # Only show statistics, don't write to disk
node tools/repack.mjs <root> --file <path>    # Process only specified files (can be multiple times)
node tools/repack.mjs <root> --min-frames 64 --min-age-ms 60000

It is recommended to run --dry-run first to view statistics, confirm the scope and expected benefits, and then execute the actual operation. --file can be passed multiple times, making it suitable for processing only a few specific sessions; --min-frames and --min-age-ms are used to customize thresholds.

Security Design

Repacking replaces the session file on disk, making security the plugin’s primary focus. Measures include:

  1. Only process .jsonl.zstd files, skipping files whose modification time (mtime) is less than minAgeMs ago to avoid active writes.
  2. Skip the current live session.
  3. Perform a byte-level equivalence check before replacement: the plaintext extracted from the new file must be identical to the original plaintext.
  4. Perform another stat comparison of size and mtime before replacement; if the file was appended to concurrently during this period, abort the operation.
  5. Torn tails (incomplete frames) are skipped directly, leaving them to be handled by DSH’s own repair path.
  6. Writing uses a temporary file + fsync + atomic rename, which is isomorphic with the official backend on Windows.

Additionally, the server is tested to be compatible with appending new frames (e.g., session/end-seed) to repacked files, and appended files can be repacked again; the operation is idempotent.

Applicability and Notes

Suitable scenarios: deployments with long session history, slow opening, and where the frame count of old sessions has already solidified and cannot be reduced on its own. With background periodic maintenance, this can be automated.

Points to note:

  • Once the frame count of an old file has solidified, it cannot be retrospectively compressed; it can only be repacked using this plugin or the CLI. If you want future logs to generate fewer frames, you can increase writeBatchMaxDelayMs (default 200ms); this is a trade-off regarding durability.
  • The plugin runs with the permissions of the current DSH process and will directly replace session files. Before installing, it is recommended to review the source code and license, and verify it using --dry-run in a test environment first.

Conclusion

dsh-session-repacker solves a specific problem: the tens of thousands of zstd logs left behind by DSH’s batch writing slow down the reading of old sessions. It does not alter data semantics but restores the files to the official native two-frame format, achieving approximately 6x faster opening speeds and about half the volume, while providing a complete set of security protections. Under DSH’s philosophy of “everything is a plugin,” this is a typical storage-layer maintenance plugin.

  • Directory: https://www.skillhub.cn/plugins/kkishapppy/dsh-session-repacker
  • GitHub: https://github.com/kkishapppy/dsh-session-repacker