Summary
ruflo memory store and ruflo memory search (and likely all other memory * subcommands) functionally complete in milliseconds but the Node process never exits. Reproducible on v3.5.75 (latest at the time of writing, 2026-04-07).
This appears to be a regression or incomplete fix of #1453 ("fix: ruflo memory subcommands hang after completion — process.exit() missing from CLI entry point"), which was marked closed on 2026-04-02 but the symptom is still present.
Related: PR #1441 ("fix(cli): process.exit at entry point to prevent ONNX event loop hang") is marked open and may be the actual fix that hasn't shipped yet.
Environment
- Ruflo / claude-flow version: v3.5.75 (verified via
ruflo --version)
- Install method:
npm install -g ruflo@latest (global, not npx-cached)
- Node: v24.14.1
- npm: v11.11.0
- OS: macOS 14 (Darwin 25.4.0, arm64)
Reproducer
mkdir -p /tmp/ruflo-mem-repro && cd /tmp/ruflo-mem-repro
ruflo init --full
ruflo memory init
ruflo memory store -k "test-key" -v "test value"
# never returns; manually kill with Ctrl+C
ruflo memory search -q "test"
# same — never returns
What actually happens
The operation completes successfully in ~3-5 ms. Output is correct. The process just never calls process.exit() after the operation finishes.
Captured via background + sleep + kill pattern (the workaround):
ruflo memory search -q "test" > /tmp/mem.log 2>&1 & PID=$!
sleep 3
kill -9 $PID
cat /tmp/mem.log
Output of cat /tmp/mem.log after killing the hung process:
[INFO] Searching: "test" (semantic)
Search time: 3ms
+----------------------+-------+-----------+----------------------------+
| Key | Score | Namespace | Preview |
+----------------------+-------+-----------+----------------------------+
| test-key | 0.43 | default | test value |
+----------------------+-------+-----------+----------------------------+
[INFO] Found 1 results
The actual semantic search runs in 3 ms and returns the right result. The hang is purely the Node process not exiting after the function returns.
Expected
ruflo memory store ... and ruflo memory search ... should print their output and exit cleanly with exit code 0, just like ruflo --version, ruflo doctor, and other working subcommands.
Workaround currently in use
ruflo memory <subcommand> ARGS > /tmp/mem.log 2>&1 & PID=$!
sleep 3
kill -9 $PID 2>/dev/null
cat /tmp/mem.log
Works reliably because the actual operation takes <10 ms; the sleep is only there to make sure stdout is flushed before the SIGKILL. Anything that uses ruflo memory * programmatically has to wrap every call in this pattern, which is painful in scripts and impossible in interactive npx use.
Suspected root cause
Same family as #1453, #1428, and #1395: something keeps the Node event loop alive after the user-facing operation completes — most likely the ONNX worker threads (the agentic-flow embedding subsystem the memory tools use for the 384-dim semantic vectors), or housekeeping timers that aren't unref()-ed.
#1269 added .unref() to housekeeping timers but the symptom returned. PR #1441 proposes adding an explicit process.exit(0) at the CLI entry point after the command's main returns — that would force-exit regardless of dangling event loop refs. Whatever shipped between #1453 closing and v3.5.75 either doesn't cover the memory store / memory search paths or was rolled back.
Why this matters
Memory store and search are foundational to the self-learning loop the README pitches at L613-620 (the "LEARN → COORD → EXECUTE → REMEMBER" cycle). With these commands hanging, the cycle is broken for anyone scripting against ruflo memory *. The workaround works for shell users but doesn't help the MCP path or any programmatic consumer.
Happy to help
If a maintainer wants me to:
- Run the reproducer with extra debug flags
- Test a specific commit / PR build
- Capture an active-handles dump (
process._getActiveHandles()) at the moment of hang
just say the word and I'll attach the output to this thread.
Summary
ruflo memory storeandruflo memory search(and likely all othermemory *subcommands) functionally complete in milliseconds but the Node process never exits. Reproducible on v3.5.75 (latest at the time of writing, 2026-04-07).This appears to be a regression or incomplete fix of #1453 ("fix: ruflo memory subcommands hang after completion — process.exit() missing from CLI entry point"), which was marked closed on 2026-04-02 but the symptom is still present.
Related: PR #1441 ("fix(cli): process.exit at entry point to prevent ONNX event loop hang") is marked open and may be the actual fix that hasn't shipped yet.
Environment
ruflo --version)npm install -g ruflo@latest(global, not npx-cached)Reproducer
What actually happens
The operation completes successfully in ~3-5 ms. Output is correct. The process just never calls
process.exit()after the operation finishes.Captured via background + sleep + kill pattern (the workaround):
Output of
cat /tmp/mem.logafter killing the hung process:The actual semantic search runs in 3 ms and returns the right result. The hang is purely the Node process not exiting after the function returns.
Expected
ruflo memory store ...andruflo memory search ...should print their output and exit cleanly with exit code 0, just likeruflo --version,ruflo doctor, and other working subcommands.Workaround currently in use
Works reliably because the actual operation takes <10 ms; the sleep is only there to make sure stdout is flushed before the SIGKILL. Anything that uses
ruflo memory *programmatically has to wrap every call in this pattern, which is painful in scripts and impossible in interactivenpxuse.Suspected root cause
Same family as #1453, #1428, and #1395: something keeps the Node event loop alive after the user-facing operation completes — most likely the ONNX worker threads (the
agentic-flowembedding subsystem the memory tools use for the 384-dim semantic vectors), or housekeeping timers that aren'tunref()-ed.#1269 added
.unref()to housekeeping timers but the symptom returned. PR #1441 proposes adding an explicitprocess.exit(0)at the CLI entry point after the command's main returns — that would force-exit regardless of dangling event loop refs. Whatever shipped between #1453 closing and v3.5.75 either doesn't cover thememory store/memory searchpaths or was rolled back.Why this matters
Memory store and search are foundational to the self-learning loop the README pitches at L613-620 (the "LEARN → COORD → EXECUTE → REMEMBER" cycle). With these commands hanging, the cycle is broken for anyone scripting against
ruflo memory *. The workaround works for shell users but doesn't help the MCP path or any programmatic consumer.Happy to help
If a maintainer wants me to:
process._getActiveHandles()) at the moment of hangjust say the word and I'll attach the output to this thread.