OpenCode Undo vs MemoryRouter: What Survives a Revert?

John Rood··5 min read

Undoing a failed implementation should not mean paying for the same investigation next week.

OpenCode's /undo gives you a way back from a change. MemoryRouter gives the next session somewhere to look for what that attempt taught you. The part worth saving is why the attempt failed.

These tools have different jobs. A successful MemoryRouter save is outside OpenCode's rollback. That makes the lesson durable, and it also means an incorrect memory needs its own correction.

What OpenCode actually undoes

OpenCode already has session history. /sessions reopens earlier conversations, and /compact summarizes a long one. It does not need MemoryRouter just to resume work.

The OpenCode TUI reference describes /undo more specifically: it removes the last user message and the responses after it. It also rolls back the associated file changes. File rollback uses Git, so it requires a Git repository. /redo is available after an undo.

That is a useful native recovery path. It is not a transaction that reverses every effect of a tool call.

In OpenCode 1.19.5's revert implementation, rollback works with file snapshots and the session's revert point. It does not send compensating requests to remote MCP services. Removing the conversation turn that called store_memory therefore does not remove the memory that call saved.

Action OpenCode's native behavior MemoryRouter consequence
/undo Rewinds the conversation and its file changes Previously saved memories remain
/redo Redoes the previously undone message Does not turn a saved lesson into a different memory
/compact Summarizes the active conversation Does not compact the external vault
/new Opens another session That session can search the connected vault

This comparison covers OpenCode's documented TUI commands and its 1.19.5 implementation, not a custom plugin that adds its own cleanup behavior.

Keep the finding, not a false statement about the code

Consider a made-up CSV import experiment. Converting account identifiers to numbers looks convenient until a fixture shows that 00127 becomes 127. You undo that implementation.

A useful memory would be:

In the demo Ledgerbox importer, numeric conversion lost leading zeroes in account identifiers. That approach was rejected. Preserve those identifiers as strings.

It would not be:

Ledgerbox converts account identifiers to numbers.

Both statements could have appeared during the work. Only one belongs in the next task's context after the experiment fails.

I would finish the rollback before deciding what to save. Only a verified finding gets my approval for storage. That avoids turning a temporary implementation into a durable claim about the project. Keep the regression test in the repository too; memory explains the decision, while the test checks the behavior.

The payoff comes when you tackle a different importer later. OpenCode can search for the earlier finding without you reviving the abandoned implementation or reconstructing why you dropped it.

Where MemoryRouter fits

The OpenCode connection guide documents a remote MCP server at https://mcp.memoryrouter.ai/mcp. Its opencode.json entry uses type: "remote" and requests memories:read memories:write through oauth.scope.

Authentication runs separately:

opencode mcp auth memoryrouter

The browser consent flow selects the vault. opencode mcp auth list checks authentication; a "connected" label from opencode mcp list alone is not enough because MemoryRouter exposes tool discovery before sign-in.

OpenCode keeps its existing model provider. There is no MemoryRouter hook package for OpenCode: saves and searches depend on the model calling the MCP tools. An instruction to remember a lesson is not proof that it was stored.

Once saved, the memory outlives OpenCode's session and its context compaction. Another supported client connected to that vault can retrieve it too. The MCP integration overview describes those client options.

The default guide requests read and write access, not deletion. If a saved finding is wrong, undoing the chat cannot fix it. The MCP tool reference documents separate deletion permissions and dashboard removal. A second store_memory call adds an entry; it does not overwrite the first.

A small test before trusting a real lesson

The following check uses synthetic content. Run it in a disposable OpenCode session with your own vault.

  1. Ask OpenCode to store this exact test memory: "Demo Ledgerbox import trial L27 rejected numeric account identifiers because they lost leading zeroes." Inspect the store_memory result, then search for L27 until the saved entry appears. A queued write may need time to become searchable; do not keep saving duplicates.
  2. Use /undo to rewind the test exchange, including the turn that saved the memory. The stored entry is independent of those messages.
  3. Use /new, then request: "Use MemoryRouter to find the rejected approach in Ledgerbox import trial L27 and explain the reason." Leave the answer out of the prompt.
  4. Read the returned search_memories entry. The expected evidence is the saved finding about leading zeroes, not a confident guess from the assistant.

Keep this experiment separate from real file edits so you know what you are rewinding.

Start keeping OpenCode findings in MemoryRouter