There's not an out-of-the-box, native way to do this, at least as of the current version (Blender 3.6). However, you can write a script using the Python API.
- Creating a node: https://docs.blender.org/api/current/bpy.types.NodeTree.html#bpy.types.NodeTree.nodes
my_node = my_node_tree.nodes.new('ShaderNodeSeparateXYZ')
- Setting a node's position: https://docs.blender.org/api/current/bpy.types.Node.html#bpy.types.Node.location
my_node.location = (100, 200)
- Attaching nodes: https://docs.blender.org/api/current/bpy.types.NodeTree.html#bpy.types.NodeTree.links
- To get the sockets, you can also reference the inputs/outputs by name (
my_node.outputs["X"]), but I've found you sometimes run into name conflicts with this approach, so I don't recommend it. Using the socket's index guarantees you don't get any collisions, but these often need to be found programmatically. The sockets can be hidden either by a node group creator or by a node setting changing the visible inputs and outputs, so the first visible output socket doesn't necessarily correspond to
- Creating a group: For this, you want to create a new node of the appropriate type (
'CompositorNodeGroup'), and then set its
node_tree attribute with the one you want. You'll likely want to set up inputs and outputs for the group, as well, which you can find some documentation here https://docs.blender.org/api/current/bpy.types.NodeTree.html#bpy.types.NodeTree.inputs.
my_group_node = my_node_tree.nodes.new("ShaderNodeGroup")
my_group_node.node_tree = bpy.data.node_groups.new(type="ShaderNodeTree", name="Shader Node Tree 2")
my_group_node.node_tree.inputs.new("NodeSocketInt", "An Integer Input")
my_group_node.node_tree.outputs.new("NodeSocketColor", "A Color Output")
- Muting: https://docs.blender.org/api/current/bpy.types.Node.html#bpy.types.Node.mute
As for a solution that does all this automatically, I've created an open source add-on that does all this for Geometry Nodes and Shader Nodes for Blender 3.0-3.6, with work in progress for Compositing Nodes.