Python - Grasshopper - Purge Third Party Plugin Components/Find & Delete


I have a pesky plugin component I can’t manually track down in my script. It is List Indices from Pufferfish (no offense to Pufferfish, great plugin!).

I need to remove it from my script as I am nativizing the script, removing all third party plugins and switching to vanilla GH only.

I’ve manually combed through every node in my script and every cluster and nested cluster and cannot find the component anywhere, however, when I uninstall Pufferfish and open the script it claims List Indices as an unrecognized object, meaning it is somewhere in my script. (Yes I have tried the “Search” feature) and purged all occurrences of this component but I have a feeling a single (or maybe 2 or so) still remain somewhere that I cannot find…

So far, I have leveraged a script I found on the forums that lists all third party plugins in the main graph but it does not work on nested graphs AKA clusters.

Also I’ve created a similar python script attempting to find all instances of a comp by search name and then my next step was to “select” the found components automatically but I’m stuck on what method to use to select them?

You can see here both scripts return a match if the component is in graph space:

However, if it is nested inside of a cluster, no good:

Is there another way I can somehow purge third party plugins from my script or drill down into clusters to search there as well?

Thanks so much, I’ve combed through my script over 3 times now looking for it line by line/node by node and can’t find the List Indices node…

Here’s my python code thus far:

import Grasshopper as gh
import System

from re import findall

pattern = r"ListIndices"
comp_ids = []
comp_names = []

if Enable:
    comps = ghenv.Component.OnPingDocument().Objects

    for comp in comps:
        comp_id = comp.InstanceGuid
        comp_name = comp.Name

    # Find Component Named "Search Name" In Grasshopper Document
    if SearchName in comp_names:
        index = comp_names.index("List Indices")
        comp_guid = comp_ids[index]
        print("Found at index:", index)
        print("Matching ID:", comp_guid.ToString())
        found_comp = ghenv.Component.OnPingDocument().FindObject(comp_guid, True)
        print found_comp
        print("Component Not Found")

And I’ll attach a gh definition for testing (23.9 KB)

I appreciate the help!

It looks like MetaHopper can find and select components but also does not work with components inside clusters:

Get Component By NickName->Select Component In Grasshopper Canvas:

Ha, I was about to suggest that.
You could explode all clusters temporarily to find the location of the culprit.
Once you know where it’s at, reopen the file and delete it manually.

I thought about that but I have quite a few clusters in my script. Can I explode all clusters simultaneously or is it going to be a find one->right click->explode on to the next?

Grrrr, doesn’t seem like it.

However you can test if your object is a cluster and if it’s the case access the components inside it via the Document() method.

Here is C#…

   foreach(IGH_DocumentObject igho in GrasshopperDocument.Objects)
      if (igho.ComponentGuid == Grasshopper.Kernel.Special.GH_Cluster.ClusterComponentId)
        GH_Cluster ghcluster = igho as GH_Cluster;
        GH_Document gdoc = ghcluster.Document("");

        A = gdoc.ObjectCount; // search for your component here


1 Like

Thanks @magicteddy, unfortunately I’m in Rhino 8 WIP and the C# editor is all bugged out and I can’t even type code in it let alone copy paste.

If only that was only the C# editor :grimacing:

I’ll have a look at this.

Thanks, I’m working up a python version of what you shared. Will share shortly if I understood it correctly

The autocompletion in the editor is really a great enhancement.

It works !

using Grasshopper.Kernel.Special;
using System.Linq;

    List<GH_Cluster> allclusters = new List<GH_Cluster>();
List<IGH_DocumentObject> connectedObj = GrasshopperDocument.ActiveObjects().Where(ao => this.Component.DependsOn(ao)).ToList<IGH_DocumentObject>();

    foreach(IGH_DocumentObject igho in GrasshopperDocument.Objects)
      if (igho.ComponentGuid == Grasshopper.Kernel.Special.GH_Cluster.ClusterComponentId)
        GH_Cluster ghcluster = igho as GH_Cluster;
        GH_Document gdoc = ghcluster.Document("");

        foreach(IGH_DocumentObject ighc in gdoc.Objects)
            if(ighc.ComponentGuid == connectedObj[0].ComponentGuid)

    cluster = allclusters; (4.1 KB)

1 Like

Amazing, going to check this out now. and on a side note.

Welcome to the hellscape that is Exploding all clusters on a 7000+ component definition :joy::

Makes me think of Unreal Engine - Blueprints From H*ll

Here’s the “explode” code I cobbled together for what its worth (Python):

import Grasshopper as gh
import System

Id_List = []

# Iterate over all objects in the Grasshopper document
for igho in ghenv.Component.OnPingDocument().Objects:
    # Check if the object is a cluster
    if igho.ComponentGuid == gh.Kernel.Special.GH_Cluster.ClusterComponentId:
        # Add the cluster ID to the list

# Explode all clusters in the Grasshopper document
if Explode:
    for cluster_id in Id_List:
        cluster = ghenv.Component.OnPingDocument().FindComponent(System.Guid(cluster_id))
        if cluster and isinstance(cluster, gh.Kernel.Special.GH_Cluster):

# Print the list of cluster IDs
IDs = Id_List

I found it… the hunt for the elusive pufferfish is complete.

Turns out it was inside a cluster that I had updated everywhere (entangled) and there was one disentangled version with the List Indices inside. Good grief that was painful.

But this was a fun learning experience in cluster access!

Thanks for all your help @magicteddy !!