How to Capture and Replay Undo/Redo Actions in Grasshopper Python?

Hi everyone,

I’m developing a Python tool to help teachers and students track Grasshopper modeling history by recording and replaying undo/redo actions or saving versioned states of a definition. The goal is to let users review and reload past actions step-by-step, so its easier to understand workflows and automatic version control system.

I’ve managed to retrieve GH_UndoServer.UndoNames and UndoGuids, which provide action names (e.g., “Add Component, “Delete”, “Move”). However, I can’t find a way to retrieve the actual action details and apply them again.

What I’m Trying to Achieve:

1 Can we programmatically replay an action? (e.g., push an undo/redo record back to Grasshopper)
2 If not, can we at least extract what changed? (e.g., slider value update, menu option toggled, component deleted)
3 If that’s also impossible, can we identify which specific component was affected?

Any suggestions on how to retrieve, store, and reuse later? Any insights are appreciated!

Use C# or Iron Python, and look through the SDK. Attempting to work with native Grasshopper .Net objects, via CPython 3, via PythonNet will inevitably lead to tricky bugs.

Trying to hack your own solution together to recreate an object model of whatever Grasshopper does, will inevitably lead to tricky bugs. If the idea relies on something that’s not in the SDK, in my opinion that makes it a non-starter if you’re doing this for free.

I think there’s an event (OnDocChange?) that the component could listen to, to kick things off, but I’ve never tried using that myself.

My instinct is, that the code should run in a separate process or ghdoc. If it runs in the same ghdoc as the one it is monitoring, it needs to exclude the internal changes it makes itself, from the targeted captured actions. Either approach may well still lead to tricky bugs.

1 Like

Thanks, James. Yeah, I think I’m just trying to invent something that doesn’t exist yet—definitely a deep rabbit hole. I’ll check out the OnDocChange event and see if it helps. Running it in a separate process or ghdoc is a smart idea, hadn’t thought of that before. Makes sense to keep things isolated to avoid conflicts. Appreciate the input!

1 Like