@openclaw/fs-safe/store
The store subpath bundles two managed wrappers around the same safe-write primitives root() uses:
import {
ensureJsonDurableQueueDirs,
fileStore,
fileStoreSync,
jsonStore,
loadPendingJsonDurableQueueEntries,
resolveJsonDurableQueueEntryPaths,
writeJsonDurableQueueEntry,
type FileStore,
type FileStoreOptions,
type FileStoreSync,
type JsonStore,
type JsonStoreOptions,
} from "@openclaw/fs-safe/store";
| Helper | Use it for |
|---|---|
fileStore() | Multi-file directories with safe relative paths, size limits, atomic replacement, stream writes, copy-in, and TTL-based pruning. |
fileStoreSync() | Synchronous variant of fileStore() for places that genuinely cannot await. |
jsonStore() | A single keyed JSON state file with explicit fallback, atomic writes, and optional sidecar locking around read-modify-write updates. |
| Durable JSON queue helpers | Append/load/ack JSON entry files using atomic writes and delivered markers. |
| Private file-store mode | fileStore({ private: true }) for credentials, tokens, and per-agent state at 0600 files under 0700 directories. |
fileStore().json("rel.json") and jsonStore({ filePath }) are intentionally separate primitives. Use fileStore().json(...) when JSON state lives alongside other files in the same managed directory; use jsonStore({ filePath }) when you have a single absolute path and want the keyed JSON shape directly.
#Picking a shape
- Multi-file directory under one root — reach for
fileStore(). It exposeswrite,writeJson,writeText,writeStream,read*,open,copyIn,remove, andpruneExpiredagainst safe relative paths. - One JSON state file — reach for
jsonStore({ filePath }). Itsupdate()andupdateOr()methods cover the merge-into-defaults and read-modify-write cases. - Credentials or tokens — pass
private: truetofileStore(). Same store shape; writes route through the secret-file atomic path with0600/0700permissions. - Durable work queues — use the durable JSON queue helpers when each work item is a standalone JSON file and acknowledgement is represented by moving it through a short-lived
.deliveredmarker.
#Durable JSON queues
The durable queue helpers are intentionally low-level. They do not decide retry, dedupe, or recovery policy; they just provide the filesystem mechanics that several queue implementations otherwise rewrite by hand.
await ensureJsonDurableQueueDirs({ queueDir, failedDir });
const paths = resolveJsonDurableQueueEntryPaths(queueDir, id);
await writeJsonDurableQueueEntry({
filePath: paths.jsonPath,
entry,
tempPrefix: "queue",
});
const pending = await loadPendingJsonDurableQueueEntries({ queueDir, tempPrefix: "queue" });
id must be a single safe path segment: non-empty, not dot-prefixed, and made from letters, numbers, _, -, and .. Slashes, backslashes, NUL bytes, ., and .. are rejected.
Use ackJsonDurableQueueEntry() after durable processing succeeds and moveJsonDurableQueueEntryToFailed() when the caller wants to quarantine an entry for inspection.
#Related pages
fileStore— full API for the multi-file store.jsonStore— single-file JSON store with locking.- Private file-store mode — credential-shaped variant.
- JSON files — lower-level
readJson/writeJsonhelpers. - Atomic writes — what
fileStoreandjsonStoreuse under the hood.