How to make your own SketchUp extension (.rbz)

A SketchUp extension is a zip file renamed to .rbz that holds exactly two things: a small loader file (my_tool.rb) that registers the extension, and a folder with the same name (my_tool/) that holds your code. Install it with Extensions › Extension Manager › Install Extension.

The structure of a SketchUp extension

Start with a script that already works in the Ruby Console (see how to run a Ruby script in SketchUp). Turning it into an extension, whether a one-click cleanup or a cut-list exporter, is mostly packaging. Trimble's extension requirements ask for this layout:

jd_hide_edges.rb        <- loader: registers the extension, nothing else
jd_hide_edges/          <- support folder, same name without .rb
    main.rb             <- your code and the menu item

The rules that matter most:

  • The loader only registers. It creates a SketchupExtension and passes it to Sketchup.register_extension. No tool logic, no loading other files.
  • Everything sits inside one uniquely named module. All extensions share one Ruby environment, so a method called run at the top level will collide with someone else's. Use your name or company plus the tool name, such as JaneDoe::HideEdges.
  • Leave the file extension off paths. Write "jd_hide_edges/main", not "jd_hide_edges/main.rb". If the extension is later encrypted, the files become .rbe and a hard-coded .rb breaks loading.
  • Load your own extra files with Sketchup.require, not require or require_relative, for the same reason.

A prefix on the file names (jd_ here) keeps your folder from clashing with another extension's folder in the Plugins directory.

A minimal working extension: loader and main.rb

This one adds Extensions › Hide Selected Edges. The loader, saved as jd_hide_edges.rb:

require "sketchup.rb"
require "extensions.rb"

module JaneDoe
  module HideEdges
    unless file_loaded?(__FILE__)
      ext = SketchupExtension.new("Hide Selected Edges", "jd_hide_edges/main")
      ext.creator     = "Jane Doe"
      ext.version     = "1.0.0"
      ext.copyright   = "2026 Jane Doe"
      ext.description = "Hides the edges in the current selection."
      Sketchup.register_extension(ext, true)
      file_loaded(__FILE__)
    end
  end
end

The code, saved as jd_hide_edges/main.rb:

require "sketchup.rb"

module JaneDoe
  module HideEdges
    def self.run
      model = Sketchup.active_model
      edges = model.selection.grep(Sketchup::Edge)
      return UI.messagebox("Select some edges first.") if edges.empty?

      model.start_operation("Hide Selected Edges", true)
      begin
        edges.each { |edge| edge.hidden = true }
        model.commit_operation
      rescue StandardError => e
        model.abort_operation
        UI.messagebox("Hide Selected Edges failed: #{e.message}")
      end
    end

    unless file_loaded?(__FILE__)
      UI.menu("Extensions").add_item("Hide Selected Edges") { run }
      file_loaded(__FILE__)
    end
  end
end

What each part does:

  • Sketchup.register_extension(ext, true) lists the extension in the Extension Manager. The true loads it now and at every start, which Trimble recommends.
  • UI.menu("Extensions") returns the Extensions menu (called Plugins before SketchUp 2015). add_item adds your command and runs the block when it's clicked.
  • The file_loaded? guard stops the menu item from being added twice if the file is loaded again.
  • start_operation and commit_operation make each click one undo step, named in Edit › Undo. If anything fails, abort_operation rolls it all back. Trimble's requirements ask for this on any command that changes the model.

Testing your extension without reinstalling

Reinstalling an .rbz after every edit gets old fast. While you work, put the loader and folder straight into your Plugins folder. To find it, run Sketchup.find_support_file("Plugins") in the Ruby Console. Restart SketchUp once so the loader registers the menu item.

After that, edit main.rb, save, and reload just that file from the console:

load File.join(Sketchup.find_support_file("Plugins"), "jd_hide_edges/main.rb")

The new version of run replaces the old one at once, and the guard keeps the menu from doubling up. Changes to the loader or to the menu text still need a restart.

Test on a copy of a real model, not an empty one. Try it with nothing selected, with a group selected, and while editing inside a component. Press Cmd+Z (Mac) or Ctrl+Z (Windows) after each run and check that one undo removes the whole change.

How to create an .rbz file

An .rbz is an ordinary zip. The catch is that the loader and the folder must sit at the top of the zip, not inside an extra wrapping folder.

On macOS

  1. In Finder, select both jd_hide_edges.rb and the jd_hide_edges folder (not the folder that contains them).
  2. Right-click and choose Compress 2 Items. You get Archive.zip.
  3. Rename it to jd_hide_edges.rbz and confirm the change of extension.

Finder may also pack hidden macOS files such as .DS_Store. For a clean archive, run this in Terminal from the folder that holds both items instead:

zip -r jd_hide_edges.rbz jd_hide_edges.rb jd_hide_edges -x "*.DS_Store"

On Windows

  1. In File Explorer, select both the .rb file and the folder.
  2. Right-click and choose Compress to › ZIP File on Windows 11 (some builds say Compress to ZIP file) or Send to › Compressed (zipped) folder on Windows 10.
  3. Rename the result from .zip to .rbz. If you can't see the .zip ending, turn on File name extensions under File Explorer's View menu first.

Installing, signing and sharing your extension

To install an .rbz, open Extensions › Extension Manager (before SketchUp 2021.1 it was under the Window menu), click Install Extension, pick the file and confirm the warning about trusted sources. If you tested from the Plugins folder, remove those copies first so the two versions don't fight.

Unsigned extensions install fine on most machines. The Extension Manager has a loading policy, set from its gear icon: under Identified Extensions Only, SketchUp loads only signed extensions, so an unsigned one won't run there. Unrestricted and Approve Unidentified Extensions let it load.

  • Sharing with a colleague or client: send the .rbz. If their policy blocks unsigned code, sign it through Trimble's Extension Signing Portal, which adds a signature file to the package (and can optionally encrypt your code).
  • Publishing on Extension Warehouse: submit the unencrypted .rbz through Trimble's developer process. Trimble reviews it against the extension requirements, then signs and (by default) encrypts it. The title and version you type in the form must match the ones in your SketchupExtension.

If you plan to publish, run RuboCop-SketchUp over your code first. It catches many requirement problems before review, such as global variables, leftover puts calls and a loader that does too much.

Turn a working prompt into an extension with MakeIt4Me

Writing the tool is usually the hard part, not the zip. MakeIt4Me (our product) connects an AI agent on your computer to your open SketchUp model, so you can describe a tool, watch the agent build and test it on your real model, and correct it until it behaves.

When it works, say "make this a plugin". The bundled sketchup-export-plugin skill asks what to call it, then packages the Ruby in the layout above: a loader, a support folder, its own namespace, a menu command and one undo step per run. It installs the extension into your Plugins folder and loads it live, so the menu command works with no restart. It also saves a shareable .rbz on your Desktop.

The result is plain Ruby that runs on its own, with no agent needed. Signing and Extension Warehouse submission are still up to you. For how this compares with writing it yourself or hiring a developer, see making your own plugin.

Questions

Do I need to know Ruby to make a SketchUp extension?

To write one by hand, yes, plus some of the SketchUp Ruby API. A good start is to get a script working in the console, then wrap it as shown above. Using ChatGPT to write SketchUp Ruby scripts covers getting help with the code itself.

What is the difference between a .rb and an .rbz file?

A .rb file is one Ruby script. An .rbz is a zip of a loader .rb and its folder, which the Extension Manager can install in one step.

Why doesn't my extension show up after installing?

Check that the zip has the loader and folder at its top level, that the path in SketchupExtension.new matches the folder name, and that the extension is enabled in the Extension Manager. Errors while loading show up in the Ruby Console.

Do I have to sign my extension?

No, unless the people using it have their loading policy set to Identified Extensions Only. Extension Warehouse signs extensions for you when it publishes them.