Writing Your First Code
Welcome!
Are you curious about making extensions or automatic tasks in SketchUp but just don't know where to start? Then this article is for you!
What Is Code?
Simply put, code is the instructions we give computers for what they should do. Early computing devices used cogged wheels and later solenoids and relays, and could only carry out the exact task they were physically built for. With modern programmable computers, the instructions are read from memory, and can be changed without rebuilding the machine. You can customize what your computer is doing and build your own digital tools that you share with the world, just by tapping a keyboard.
Still, the computer is just a machine. It does what you tell it to do, for good and for bad. Unlike a human, a computer has no imagination and no ability to guess or fill in the gaps. This is why the code doesn't work if the syntax or spelling isn't right.
What is an API?
An API, Application Programming Interface, is where two layers of software meet When you want to use an electrical appliance, you don't need to punch a hole in your wall and connect directly to the electric wires. Instead there's an agreement between appliance manufacturers and builders for a standardized power plug. An API is a bit like this. It's an agreement of how a software can be interacted with.
APIs allow for building layers of compartmentalized software. The technical bits and pieces within can be replaced, but as long as the API remains the same, the software can still interact and function. SketchUp is built using lower level system APIs and on top of it you can build extensions, using the SketchUp Ruby API.
Similarly to how a builder doesn't need to consider every conceivable appliance you may plug in, or how Microsoft and Apple doesn't have to think of any possible application someone could build, SketchUp doesn't have to imagine every extension that could exist. By using an API, we can stand on the shoulders of giants, while having a high degree of freedom in what we can create.
What is Ruby?
Ruby is a programming language used, among other things, for the SketchUp extension API. SketchUp has other APIs for other services, but the Ruby API is the one allowing live access to the SketchUp desktop application, to add custom tools and other functionality.
Writing your first code
Let’s write our first piece of Ruby code in SketchUp! Start by opening the Ruby Console (Extensions > Developer > Ruby Console). The Ruby console is a tool for testing and debugging, and a good place to start.
The bottom part of the console has a text area where you can write and the above part shows your previous inputs and SketchUp’s responses to them.
You can try writing 4 + 4 and press Enter. SketchUp will evaluate the code and show you the result 8.

You can type Sketchup and press enter (yes, SketchUp with a lowercase U). This returns the Sketchup module which is where much of the SketchUp Ruby API functionality is defined. Modules are a way to organize things in a program, like drawers or boxes.
You can continue by typing Sketchup.active_model. This calls a method named active_model that belongs to the Sketchup module. In Ruby, module and class names are typically written in CamelCase (uppercase letters to convey new words) and method names in snake_case (all lowercase, with underscore between the words). In programming you typically don’t use spaces inside of a single name; you can think of them as compound words. Modules, classes and objects can be thought of as nouns whereas methods are verbs - actions you invoke.
Sketchup.active_model returns a Sketchup::Model object representing, you guessed it, the SketchUp model you currently have open. A SketchUp model contains a bunch of things like components, materials, tags and more, but we’ll focus on the basic geometry for now.
Sketchup.active_model.entities returns a Sketchup::Entities collection object. This is the container of basic geometry such as edges and faces, but also complex objects like groups, components and images. Each component definition in SketchUp has its own Entities collection, and the model also has one for everything placed directly in the model, not contained by groups or components.
Drawing Something
Now that we have a reference to an Entities collection, we can add something to it. One of the most basic things would be an edge.
Sketchup.active_model.entities.add_edges([0, 0, 0], [1.m, 0, 0])
Unlike both active_model and entities, the add_edges method needs arguments to work. We can’t just draw an edge without saying where we want it. This code passes two arguments, both being Arrays (lists) of 3 coordinates each. The first represents the origin and the second a point 1 m away from the origin along the X (red) axis.
Technically, m is a method on the Numeric class, similarly to entities being a method on the Sketchup::Model class. This is why we need a dot between 1 and m. The m method is used in SketchUp to convert from meters to SketchUp’s [internal unit](Lengths and Units in SketchUp.md), inches.
Drawing a Face
With the same syntax and additional methods we can draw more advanced things, like a face.
Sketchup.active_model.entities.add_face([
[0, 0, 0],
[1.m, 0, 0],
[1.m, 1.m, 0],
[0, 1.m, 0]
])
This draws a 1 meter by 1 meter face. Square brackets are again used for arrays, this time an array of arrays. The line breaks and indentation just makes the code easier to read. In Ruby two spaces are typically used for indentation.
As the code gets longer it can be nice to type or copy it into a text editor, such as Notepad or TextEdit. The code can still be copied into the console to be run.
You may notice the face is upside down, with the blue back side up. For reasons lost to history, SketchUp was historically designed to draw faces upside down on the X-Y plane. Maybe because PushPull at the time didn’t automatically draw things the correct side out, but rather created inside out geometry if not used from the back of the starting face. SketchUp 2022 was changed to draw faces front side up, as you’d probably expect, but the API behavior was kept for backward compatibility. Changing the API at this point would sadly mean any extension built with the assumption that these faces on the X-Y plane are always drawn front side down would break.
We can turn the face front side up by reversing the face.
face = Sketchup.active_model.entities.add_face([
[0, 0, 0],
[1.m, 0, 0],
[1.m, 1.m, 0],
[0, 1.m, 0]
])
face.reverse!
Or better, we can check if the face is upside down, and only reverse it if needed.
face = Sketchup.active_model.entities.add_face([
[0, 0, 0],
[1.m, 0, 0],
[1.m, 1.m, 0],
[0, 1.m, 0]
])
face.reverse! unless face.normal.samedirection?(Z_AXIS)
This code introduces our first variable, face. Variables can be used to hold on to a reference to an object to use it later. We could also chain the reverse! method directly after add_face() with a dot in between, but that would make the code harder to read, and we couldn’t reference the face a second time to determine if it should be reversed or not.
This code also introduces our first conditional. Instead of always reversing the face, we now only reverse it if it is indeed upside down. The code before unless is only evaluated if the expression after evaluates to false. This can be combined with calling the normal method on the face to get its normal (perpendicular) vector. We can then call the samedirection? method on the vector to see if it’s parallel and co-directional with another vector. Z\_AXIS, the vector we compare to, is a constant, and really just a shorthand for Geom::Vector.new(0, 0, 1), to give us less to type and an easier code to read.
The exclamation mark in reverse! and question mark in samedirection? are simply part of the method names. By the naming conventions of Ruby, a question mark is used at the end of a method that checks something and returns a Boolean (true or false) value and an exclamation mark is often used to show that the method will change the object (in this case the face).
Drawing a Cube
Now that we have a face with the front side up, we can pushpull it into a cube!
face = Sketchup.active_model.entities.add_face([
[0, 0, 0],
[1.m, 0, 0],
[1.m, 1.m, 0],
[0, 1.m, 0]
])
face.reverse! unless face.normal.samedirection?(Z_AXIS)
face.pushpull(1.m)
Finally we have something three dimensional!
Undo Support
You may already have noticed that if you want to revert the changes to have a clean slate between iterations, undo only reverts one method call at a time, not the full code snippet. This is just mildly annoying for a 3 step operation, but could make the undo functionality unusable in an actual extension that may make hundreds of model changes at once. This is actually a main reason we reject submissions to Extension Warehouse.
To fix this, wrap the code between start_operation and commit_operation.
model = Sketchup.active_model
model.start_operation("Draw Cube", true)
face = model.entities.add_face([
[0, 0, 0],
[1.m, 0, 0],
[1.m, 1.m, 0],
[0, 1.m, 0]
])
face.reverse! unless face.normal.samedirection?(Z_AXIS)
face.pushpull(1.m)
model.commit_operation
Since start_operation and commit_operation are methods called on the Sketchup::Model object, it makes sense to break out model as a variable so we don't have to call Sketchup.active_model multiple times.
start_operation needs a name to display in the Edit > Undo command. The second argument is optional and used to prevent SketchUp from updating the view between each step. Again, this makes little difference when we just make 3 model changes, but for an actual extension with potentially hundreds or thousands of changes, it has a huge impact on performance.
Variables and User Input
The code so far just draws the same box every time. It’s cool to do it with code, but it could as well be a component you place each time you need one. The real value of programming is added when we introduce variable data and inputs!
To start with, we can extract the measurements and define them at the top.
side = 1.m
model = Sketchup.active_model
model.start_operation("Draw Cube", true)
face = model.entities.add_face([
[0, 0, 0],
[side, 0, 0],
[side, side, 0],
[0, side, 0]
])
face.reverse! unless face.normal.samedirection?(Z_AXIS)
face.pushpull(side)
model.commit_operation
Or maybe we want the measurements to differ. When doing this we can also tweak the operation name to be more generic.
length = 1.m
depth = 50.cm
height = 100.mm
model = Sketchup.active_model
model.start_operation("Draw Box", true)
face = model.entities.add_face([
[0, 0, 0],
[length, 0, 0],
[length, depth, 0],
[0, depth, 0]
])
face.reverse! unless face.normal.samedirection?(Z_AXIS)
face.pushpull(height)
model.commit_operation
This code also shows some different methods on the Numeric object for other units of measurements. You can also try .inch, .feet and .yard.
To control these dimensions from within the user interface of SketchUp, not by editing the code, we add an inputbox.

length = 1.m
depth = 50.cm
height = 100.mm
inputs = UI.inputbox(["Length", "Depth", "Height"], [length, depth, height])
length = inputs[0]
depth = inputs[1]
height = inputs[2]
model = Sketchup.active_model
model.start_operation("Draw Box", true)
face = model.entities.add_face([
[0, 0, 0],
[length, 0, 0],
[length, depth, 0],
[0, depth, 0]
])
face.reverse! unless face.normal.samedirection?(Z_AXIS)
face.pushpull(height)
model.commit_operation
UI.inputbox can be used to let the user enter numbers, text strings, or lengths. Note how it by default shows the length in the model units.
UI.inputbox returns an Array (list) of values, corresponding to its fields. We can look up individual entries in this list using the [] method. If we press Cancel, UI.inputbox instead returns nil, representing nothingness. With the above code we run into a Ruby error as we then try to call the nonexistent method [] on nil, but we'll get back to that later.
Sticky Geometry
When playing around with the above code, you may have seen something like this.

This is what happens when drawing differently sized rectangles in the same space and push-pulling them. In SketchUp, geometry (edges and faces) is sticky and merges into a connected mesh.
Experienced SketchUp users are familiar with this and know the remedy is to make every distinct object a group or component. The same applies when using the API. Let's introduce the add_group method!
length = 1.m
depth = 50.cm
height = 100.mm
inputs = UI.inputbox(["Length", "Depth", "Height"], [length, depth, height])
length = inputs[0]
depth = inputs[1]
height = inputs[2]
model = Sketchup.active_model
model.start_operation("Draw Box", true)
group = model.entities.add_group
face = group.entities.add_face([
[0, 0, 0],
[length, 0, 0],
[length, depth, 0],
[0, depth, 0]
])
face.reverse! unless face.normal.samedirection?(Z_AXIS)
face.pushpull(height)
model.commit_operation
You can run this code a few times with different measurements and see how happily the boxes now can coexist in the same space.
Instead of adding the face directly to the model's entities, we added a group to the model's entities and added the face to the group's entities. This makes our code more stable as the newly drawn geometry cannot merge with any pre-existing geometry. In practice, this is how most extensions drawing custom objects work in SketchUp.
Writing your first method
We are not limited to the methods given to us by Ruby or SketchUp. You can create our own! Actually this is how most code is written so it can be called when needed, not just evaluated when loaded.
To define a method in Ruby, use the def (definition) keyword, followed by a space and the method name.
def sum_4_4
4 + 4
end
To invoke the method, simply type its name and press enter.
sum_4_4
This method returns 8. In Ruby, the evaluated value of the last statement in the method is what the method as a whole returns. You can also use the explicit return keyword to return earlier, and skip over the subsequent lines in the method.
def sum_4_4
return 4 + 4
4 + 5
end
In this example the line 4 + 5 is never reached, because the method always returns above it.
We can wrap our previous code in a method.
def draw_box
length = 1.m
depth = 50.cm
height = 100.mm
inputs = UI.inputbox(["Length", "Depth", "Height"], [length, depth, height])
return unless inputs
length = inputs[0]
depth = inputs[1]
height = inputs[2]
model = Sketchup.active_model
model.start_operation("Draw Box", true)
group = model.entities.add_group
face = group.entities.add_face([
[0, 0, 0],
[length, 0, 0],
[length, depth, 0],
[0, depth, 0]
])
face.reverse! unless face.normal.samedirection?(Z_AXIS)
face.pushpull(height)
model.commit_operation
end
draw_box
Note how a conditional return is used if the user cancels. Instead of an ugly Ruby error printed to the console, the method stops gracefully when the user tells it to.
We could also use a multi-line conditional, with if and end, instead of return. However, many levels of indentation makes the code harder to read as it takes some effort to pair up if and end if far apart.
def draw_box
length = 1.m
depth = 50.cm
height = 100.mm
inputs = UI.inputbox(["Length", "Depth", "Height"], [length, depth, height])
if inputs
length = inputs[0]
depth = inputs[1]
height = inputs[2]
model = Sketchup.active_model
model.start_operation("Draw Box", true)
group = model.entities.add_group
face = group.entities.add_face([
[0, 0, 0],
[length, 0, 0],
[length, depth, 0],
[0, depth, 0]
])
face.reverse! unless face.normal.samedirection?(Z_AXIS)
face.pushpull(height)
model.commit_operation
end
end
draw_box
Menu Entry
Since we defined our method we now have a code block we can call whenever we want, as opposed to it running just once when we first enter it. This is closer to how a real application works. Now we can invoke the code by a user action.
menu = UI.menu("Extensions")
menu.add_item("Draw Box") { draw_box }
{} denotes a code block that runs every time the menu entry is invoked. A handful of methods take a code block like this. Technically we could put all our previous code inside here, instead of calling a method by name, but it makes the code harder to read. It's better to break up the code in shorter, more manageable chunks that can be read and understood independently from one another.
Next Steps
These are the fundamental building blocks for coding in SketchUp. In the next article we will look into where to store the code, to build on it over time. After that we'll go into how to do some slightly more advanced drawing and how to turn it into a SketchUp Extension that can be shared with the world.
Other Resources
Ruby Documentation (not SketchUp specific)
SketchUp Ruby API Documentation