Sessions appear to exist, but a forced stop leaves resume behavior unproven.
Fastest fix: choose JSONL for single-user trials and file-oriented backups; choose SQLite only when structured queries justify it on reliable local storage, and validate every network-mounted setup before use.
This guide is for independent developers keeping coding or analysis sessions for the long term, operations teams managing many sessions on a cloud Mac, and platform owners defining audit, recovery, and storage-delivery standards.
Start with the workload, not the file extension
DeepSeek Harness is still in developer preview, and the official repository warns that compatibility-breaking changes are expected. The current repository is therefore the source of truth for available configuration, storage backends, and release behavior, not an old deployment script or a filename you found in a forum. Read the official DeepSeek Harness repository and preview warning. (github.com)
The practical distinction is simple:
- Session persistence is the authoritative event history needed to reopen or resume work.
- A derived query index is an additional structure used to filter, search, or aggregate sessions.
- A file backup is a copy or export process. It is not automatically a valid database backup.
The first decision should be based on ownership and access:
| Decision dimension | Prefer JSONL | Prefer SQLite |
|---|---|---|
| Primary user | One developer or one agent process | A team or service with repeated queries |
| Backup unit | Individual session files | A coordinated database snapshot or export |
| Inspection | Manual review, shell tools, line-oriented processing | SQL filters, joins, aggregation |
| Active disk | Reliable local filesystem | Reliable local filesystem |
| Network mount | Safer starting point for copied artifacts, still test writes | Do not assume WAL compatibility |
| Recovery responsibility | Rebuild or validate each file | Protect database, WAL, and locking behavior |
| Editorial fit score | 5/5 for trials and portability | 5/5 for query-heavy local deployments |
Verify the active storage root before touching production sessions
The question “where does DeepSeek Harness save sessions by default?” has no safe universal answer for a rapidly changing preview release. The correct path is the one selected by the version and configuration running on your Mac.
Use this discovery sequence:
- Record the exact DeepSeek Harness version or commit used by the process.
- Save the active configuration file and the environment variables that affect storage.
- Search the configuration for the session backend and session root rather than guessing from a directory name.
- Start a disposable session and write a distinctive marker such as
storage-probe-2026. - Compare recently modified files before and after the probe.
- Confirm whether the changed object is a JSONL event file, a SQLite database, or a derived index.
- Record owner, group, permissions, filesystem type, and mount location.
find "$HOME" -type f -mmin -5 2>/dev/null | sort
file /path/to/candidate
df -T /path/to/candidate
ls -lO /path/to/candidate
If the storage root is outside your home directory, repeat the inspection with the service account that actually runs the agent. A common failure is checking files as your interactive user while the daemon writes under another account. The session may be present, but the process cannot reopen it because the permissions, sandbox, or working directory changed.
Do not finish this step when a file appears. Close the process cleanly, reopen the session, and perform one minimum restore task. For example, ask the agent to identify the last completed tool action and continue from it. A generated file proves only that one write succeeded.
Use JSONL when each session should be a portable backup unit
JSONL session storage is the better first choice for individual trials, single-machine development, and environments where you want to copy one session without coordinating a database snapshot.
Its operational strengths are visible:
- A session is represented as an append-oriented text artifact.
- Standard shell tools can inspect, count, filter, compress, and hash records.
- Backup jobs can copy sessions independently.
- A damaged or incomplete tail can often be isolated without making every other session unavailable.
- Migration tooling can process records incrementally.
For a JSONL acceptance test, use this sequence:
- Start a new session on local storage.
- Generate enough activity to create user, assistant, tool-call, and tool-result events.
- Copy the active file while the process is stopped cleanly.
- Reopen the original session and confirm the latest event is present.
- Force a process interruption during active writing.
- Restart the harness and attempt to resume the same session.
- Inspect the final line and compare the last known event identifier.
- Copy the recovered file to a clean directory.
- Start a fresh process using the copy or supported import path.
- Confirm that the restored session can continue, not merely display history.
For cloud Mac operations, JSONL also gives you a simpler handoff model. You can deliver a closed session file, a manifest containing version and checksum, and a restore note. That is easier to reason about than copying a live database while its WAL is changing.
Move to SQLite when query demand becomes the bottleneck
SQLite becomes attractive when the operational problem is no longer “can I save and resume one session?” but “can I find every tool error, event type, project, time range, or session owner across a large collection?”
Typical query requirements include:
- Find sessions that invoked a specific tool.
- Filter events by date, project, model, or outcome.
- Join session metadata with event counts.
- Produce an audit report without scanning every text line.
- Build a local dashboard or retention job.
- Maintain indexes for repeated searches.
| Operational requirement | JSONL approach | SQLite approach |
|---|---|---|
| List all sessions | Scan files or maintain a separate manifest | Query a sessions table or supported index |
| Search event content | Line scan or derived index | SQL filter or full-text index if configured |
| Backup one session | Copy one file | Export rows or use a supported database backup |
| Backup active state | Coordinate file copy with process state | Include database, WAL, and recovery procedure |
| Audit reproducibility | Preserve raw event files and metadata | Preserve schema version, database, and query definition |
| Migration visibility | Compare records line by line | Compare rows, identifiers, constraints, and indexes |
| Failure boundary | Usually an individual file or tail | Potentially the database plus sidecar state |
SQLite’s sidecar files matter operationally. In WAL mode, the active state normally involves the main database, a -wal file, and a -shm shared-memory index. The official SQLite WAL documentation describes these three files and explains that the shared-memory index coordinates access between clients. Review SQLite’s WAL file format. (sqlite.org)
That means a casual command such as copying only sessions.sqlite while the process is active may produce a package that does not represent the latest committed state. Use a supported SQLite backup method, stop the writer before a file copy, or checkpoint and verify the result according to the application’s documented procedure.
Keep SQLite on local storage unless the mount passes failure tests
The most dangerous shortcut is to place a live SQLite database on a shared directory because the directory is easy for multiple Macs to reach.
SQLite’s official documentation states that WAL depends on shared memory and does not support the normal network-filesystem model where clients operate from different machines. The -shm file is part of that coordination model. See SQLite’s database file-format notes on WAL and network filesystems. (sqlite.org)
The safer architecture is:
- Keep the active SQLite database on the local filesystem of the Mac running DeepSeek Harness.
- Run the writer and query process on that same host.
- Export closed snapshots or query results to shared storage.
- Treat the shared location as a delivery or backup destination, not the live database directory.
Use this acceptance matrix before approving a shared mount:**Operational warning:** A successful open, a successful insert, or a clean first test does not prove that a network-mounted SQLite database is safe. Test lock acquisition, concurrent access, interruption, remount behavior, WAL replay, and reopen after failure.
| Test | Pass condition | Reject condition |
|---|---|---|
| Lock test | Competing access is serialized as designed | Both writers proceed or lock state is unclear |
| WAL sidecar test | -wal and -shm behavior is supported and observable | Sidecars cannot be created or are inconsistently visible |
| Abrupt-stop test | Restart recovers committed events without manual repair | Database reports corruption or loses confirmed events |
| Remount test | Reopen after mount interruption follows the documented recovery path | Process hangs, silently writes elsewhere, or resumes stale state |
| Backup test | Snapshot restores to a clean local directory | Copy opens but misses recent committed activity |
| Multi-host test | Access pattern is explicitly single-host or proven safe | Multiple hosts share an unverified live database |
Validate long-running agents through interruption and resume evidence
For continuous Agent workloads, the critical events are not ordinary writes. They are the transitions around failure:
- A tool call is recorded, but the process exits before the tool result.
- The operating system restarts during a response stream.
- The session is reopened after a long idle period.
- A cold process loads an old session and appends new events.
- A query index is stale while the primary session data is current.
A minimum runbook has five required actions:
- Write: create a representative session containing text, tool calls, tool results, and at least one long payload.
- Interrupt: stop the process during an active write, not after it has become idle.
- Restart: launch the same DeepSeek Harness version with the same storage configuration.
- Resume: reopen the session and continue with a task that depends on the last durable event.
- Inspect: compare the visible transcript, event identifiers, timestamps, and query results with the pre-interruption record.
.jsonl file can still be incomplete, and a .sqlite file can still be copied incorrectly.
Keep the test artifact. It should include the version, backend configuration, filesystem type, process command, interruption method, expected event count, observed event count, and restore result. Because DeepSeek Harness is a preview release with expected breaking changes, this record is more valuable than a one-time “works on my Mac” note. (github.com)
Migrate with a read-only old backend and a small verification set
Changing the backend is a data migration, not a configuration flip. The old backend may remain the only trustworthy recovery source until the new path has passed verification.
Use this sequence:
- Freeze new writes or define a clear cutover window.
- Record the DeepSeek Harness version, commit, storage settings, session root, filesystem type, and permissions.
- Preserve the old backend as read-only.
- Select a small representative set: a short session, a long session, a tool-heavy session, and an interrupted session.
- Import or convert only that set into the new backend.
- Compare session IDs, event types, timestamps, tool results, and visible transcript boundaries.
- Restart DeepSeek Harness and resume each migrated session.
- Run the query workload that motivated the migration.
- Back up the verified new state.
- Expand migration in batches, retaining a rollback point after each batch.
Keep old records immutable during the validation window. If the new backend fails, route new work back to the old backend or restore the last verified batch. Do not promise direct cross-version reuse while the official project warns about compatibility-breaking changes.
Choose the backend with this final operating rule
Use JSONL when your dominant requirement is independent session backup, manual inspection, portability, or low-complexity single-user operation. Use SQLite when structured queries, repeated filtering, audit views, or derived indexes justify the added responsibility, and keep the active database on reliable local storage.
For a cloud Mac, the strongest default is usually local active storage plus exported backups. You can review MACGPU’s cloud Mac environment when you need a remote machine for controlled testing, or compare available Mac rental configurations before assigning long-running session workloads.
If your current setup writes SQLite WAL directly to a shared mount, it has two real weaknesses: the database depends on filesystem locking and shared-memory behavior that may not match the mount, and a file-only backup can miss active WAL state. If it is a local JSONL setup, its main weaknesses are weaker ad hoc querying and the need to define tail-repair and indexing procedures. Renting a Mac through MACGPU can give you a cleaner single-host boundary for testing, recovery, and delivery before you commit to a permanent storage design.
That does not make rental the right answer for every workload. Buy or dedicate a Mac when you need stable long-term heavy usage, physical peripherals, or full control over the host. Use a temporary MACGPU Mac when you need an isolated migration target, a repeatable recovery test, or a remote environment without changing your primary workstation.
Your acceptance decision should be explicit:
- Single user, short trial, local disk: start with JSONL.
- Long-running agent, one host, file-oriented recovery: keep JSONL until query demand proves otherwise.
- Many sessions, structured audit queries, local disk: evaluate SQLite and a rebuildable query index.
- Live database on a network mount: reject by default and test only as an exception.
- Backend migration: keep the old backend read-only until restart, resume, query, and restore checks pass.