When the Memory Pipeline Breaks
Claude-mem’s reliability question begins at the moment its quiet side process stops behaving like the happy path. A memory can be missing because a hook never captured the event, a live generator lost an in-memory batch, a provider refused to process it, SQLite never committed it, Chroma has not indexed it, or context delivery trimmed it away. This chapter follows the worker lifecycle and the recovery choices attached to those states, so a reader can distinguish durable evidence from temporary absence instead of treating every missing memory as the same failure.
The worker’s lifecycle is deliberately outside the user’s turn
The local worker is an HTTP daemon that owns the database connection, search services, optional Chroma connection, optional transcript watcher, and the supervised observer processes. A hook can check whether the worker is alive and ready, start it lazily when necessary, and make a bounded request. The worker’s startup path initializes the database and search services in the background, so a process can be alive while still warming up. A readiness check prevents a hook from sending ordinary work to a worker that has not finished initialization.
This separation protects the primary coding session. If the worker cannot be reached or a transport request times out, the hook’s normal fallback is to let the host agent continue. The user may lose newly injected context or immediate observation processing, but the coding turn is not held open waiting for a side daemon. Repeated unreachability can become visible through a configurable fail-loud threshold and blocking feedback. The important qualification is that “non-blocking” describes transport-class worker failure, not every possible client error or an intentionally escalated persistent outage.
Once an event reaches a live worker, the session manager creates or retrieves an active session and attaches a per-session buffer. The observer generator consumes that buffer through an asynchronous iterator. A message is claimed when the generator takes it, and the buffer is signaled when another event arrives. The generator can therefore remain available while tool uses arrive at different times, allowing the observer to see a sequence rather than forcing a new model request for every fragment.
The buffer’s idle timeout gives that live generator a termination condition. If no new message arrives for three minutes, the session manager aborts the generator and the SDK subprocess is cleaned up. This is resource control, not a statement that the memory session is complete. A later tool event can start a fresh generator. The live conversation should not remain in memory indefinitely merely because a user may return to the project eventually.
The current buffer is intentionally not a durable queue that can be reconstructed by another worker process. The observer is a stateful, nondeterministic reducer: the meaning of the next event can depend on the conversation already sent to the provider. Persisting fragments while discarding that reducer state made crash replay capable of producing different or duplicate observations and could create retry storms. The implementation therefore treats the primary transcript as the durable recovery source. If the worker dies, the in-memory buffer is gone; a configured transcript adapter can replay the primary session back through shared ingestion.