makeit4me 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,255 @@
1
+ ---
2
+ name: sketchup-bridge
3
+ description: |
4
+ Control SketchUp via the makeit4me MCP server. Use when:
5
+ (1) sending Ruby code to SketchUp, (2) reading or modifying model
6
+ geometry, (3) placing/moving/deleting entities, (4) debugging Ruby eval errors
7
+ like scoping issues, (5) diagnosing visual artifacts like z-fighting or missing
8
+ geometry. Covers all MCP tools, the Ruby API cheat sheet, known gotchas, and
9
+ the screenshot-verify workflow.
10
+ author: Claude Code
11
+ version: 3.0.0
12
+ date: 2026-03-15
13
+ ---
14
+
15
+ # SketchUp Claude Bridge (MCP)
16
+
17
+ SketchUp is controlled through the **makeit4me** MCP server. All tools target
18
+ the currently active/focused model. Ruby code can be multi-line and readable —
19
+ there is no JSON escaping or shell escaping to worry about.
20
+
21
+ ---
22
+
23
+ ## MCP Tools
24
+
25
+ ### `sketchup_status`
26
+ Health check. Always call this first to confirm SketchUp is open and ready.
27
+
28
+ No parameters. Returns model title, path, and SketchUp version.
29
+
30
+ ### `sketchup_models`
31
+ List all open models.
32
+
33
+ No parameters. Returns an array of models with title, path, and active flag.
34
+
35
+ ### `sketchup_inspect`
36
+ Evaluate arbitrary Ruby in SketchUp's active model context.
37
+ The variable `model` is pre-bound to `Sketchup.active_model`.
38
+
39
+ **Parameters:** `code` (Ruby string)
40
+
41
+ **Use for reads and non-destructive queries.** For geometry changes, use `sketchup_operation` so they are undoable.
42
+
43
+ Example — count entities:
44
+ ```ruby
45
+ model.entities.length
46
+ ```
47
+
48
+ Example — get model bounds:
49
+ ```ruby
50
+ model.bounds.to_s
51
+ ```
52
+
53
+ ### `sketchup_operation`
54
+ Execute Ruby wrapped in a named undo operation.
55
+ **Always use this when creating, moving, or deleting geometry** so the user can Ctrl+Z.
56
+
57
+ **Parameters:** `name` (undo label), `code` (Ruby string)
58
+
59
+ Ruby code can span multiple lines freely:
60
+ ```ruby
61
+ grp = model.entities.add_group
62
+ grp.name = "Test Box"
63
+ ents = grp.entities
64
+ pts = [
65
+ [0, 0, 0],
66
+ [10.inch, 0, 0],
67
+ [10.inch, 10.inch, 0],
68
+ [0, 10.inch, 0]
69
+ ]
70
+ face = ents.add_face(pts)
71
+ face.pushpull(5.inch)
72
+ grp
73
+ ```
74
+
75
+ ### `sketchup_selection`
76
+ Read or manipulate the active selection.
77
+
78
+ **Parameters:** `action` ("get", "clear", "set", etc.), `entities` (optional, entity references)
79
+
80
+ ### `sketchup_screenshot`
81
+ Take a viewport screenshot. Returns the image directly — just view the result, no need to read a temp file.
82
+
83
+ **Parameters:**
84
+ - `eye` — camera position as [x, y, z]
85
+ - `target` — look-at point as [x, y, z]
86
+ - `orthographic` — true for parallel projection (optional)
87
+ - `width`, `height` — image dimensions (optional)
88
+
89
+ ---
90
+
91
+ ## Geometry Cheat Sheet (SketchUp Ruby API)
92
+
93
+ ```ruby
94
+ # Units — always use .inch / .mm / .feet / .m helpers
95
+ 10.inch # => 10 inches in SketchUp's internal unit (inches)
96
+ 2.4.m # => 2.4 meters
97
+
98
+ # Entities (top-level model geometry)
99
+ model.entities # EntityCollection
100
+ model.entities.add_face(pts) # pts = array of [x,y,z] or Geom::Point3d
101
+ model.entities.add_line(pt1, pt2)
102
+ model.entities.add_box(origin, w, h, d) # returns Array of 6 faces
103
+ model.entities.add_group # returns Sketchup::Group
104
+
105
+ # Faces
106
+ face.pushpull(dist) # AVOID for boxes — direction is non-deterministic (see build-scripts skill)
107
+ face.normal # Geom::Vector3d
108
+ face.vertices.map(&:position)
109
+
110
+ # Transform
111
+ t = Geom::Transformation.translation([dx, dy, dz])
112
+ t = Geom::Transformation.rotation(origin, axis, angle_in_radians)
113
+ model.entities.transform_entities(t, [entity1, entity2])
114
+
115
+ # Groups & Components
116
+ grp = model.entities.add_group
117
+ grp.name = "My Group"
118
+ grp.entities.add_face(...)
119
+ defn = model.definitions.add("MyComponent")
120
+ model.entities.add_instance(defn, Geom::Transformation.new)
121
+
122
+ # Materials
123
+ mat = model.materials.add("Red")
124
+ mat.color = Sketchup::Color.new(255, 0, 0)
125
+ face.material = mat
126
+
127
+ # Layers (Tags in newer SketchUp)
128
+ layer = model.layers.add("Structure")
129
+ entity.layer = layer
130
+ ```
131
+
132
+ ---
133
+
134
+ ## Known Gotchas
135
+
136
+ ### 1. `def` Creates Methods on Wrong Scope
137
+
138
+ **Symptom**: `undefined method 'my_helper' for MakeIt4Me:Module`
139
+
140
+ **Cause**: `def` inside eval creates methods on the bridge module, not as local functions.
141
+
142
+ **Fix**: Use lambdas instead:
143
+ ```ruby
144
+ # BAD - will error
145
+ def make_box(origin, size)
146
+ # ...
147
+ end
148
+
149
+ # GOOD - works in eval context
150
+ make_box = lambda { |origin, size|
151
+ # ...
152
+ }
153
+ make_box.call([0,0,0], 10)
154
+ ```
155
+
156
+ ### 2. Entity Deletion Race Conditions
157
+
158
+ **Symptom**: `reference to deleted Entity` when iterating and deleting.
159
+
160
+ **Cause**: Deleting entities while iterating invalidates references.
161
+
162
+ **Fix**: Collect to array first, then batch delete:
163
+ ```ruby
164
+ # BAD
165
+ entities.each { |e| entities.erase_entities(e) }
166
+
167
+ # GOOD
168
+ entities.erase_entities(entities.to_a)
169
+
170
+ # GOOD - with filter
171
+ to_del = entities.to_a.select { |e| e.is_a?(Sketchup::Face) }
172
+ entities.erase_entities(to_del) if to_del.any?
173
+ ```
174
+
175
+ ### 3. Materials Live on Groups, Not Always on Faces
176
+
177
+ **Symptom**: `face.material` returns nil even though the geometry appears textured.
178
+
179
+ **Cause**: SketchUp allows materials on groups/component instances. The group material overrides face materials visually.
180
+
181
+ **Fix**: Check both levels:
182
+ ```ruby
183
+ mat = group.material
184
+ mat ||= group.entities.grep(Sketchup::Face).first&.material
185
+ # Apply to group for consistency
186
+ new_group.material = model.materials["Wall Wood"]
187
+ ```
188
+
189
+ ### 4. Z-Fighting Between Coplanar Faces
190
+
191
+ **Symptom**: Flickering/clipping artifacts where two surfaces overlap.
192
+
193
+ **Cause**: Two faces on the exact same plane. GPU can't determine draw order.
194
+
195
+ **Fix**: Remove redundant coplanar geometry. Diagnose by checking overlaps:
196
+ ```ruby
197
+ target_min = [80, 90, 0]
198
+ target_max = [88, 120, 80]
199
+ model.entities.each do |e|
200
+ bb = e.bounds
201
+ if bb.min.x <= target_max[0] && bb.max.x >= target_min[0] &&
202
+ bb.min.y <= target_max[1] && bb.max.y >= target_min[1] &&
203
+ bb.min.z <= target_max[2] && bb.max.z >= target_min[2]
204
+ puts "#{e.typename} #{e.respond_to?(:name) ? e.name : ''} overlaps"
205
+ end
206
+ end
207
+ ```
208
+
209
+ ### 5. `add_group` from Exploded Entities
210
+
211
+ **Symptom**: `All Entities must have a common parent` when re-grouping exploded entities.
212
+
213
+ **Cause**: `explode` returns entities already parented to the current collection. References may be stale.
214
+
215
+ **Fix**: Explode inside a group context:
216
+ ```ruby
217
+ grp = entities.add_group
218
+ inst = grp.entities.add_instance(defn, transform)
219
+ inst.explode # explodes into grp.entities, stays contained
220
+ ```
221
+
222
+ ---
223
+
224
+ ## Error Handling
225
+
226
+ All MCP tools return an error field on failure with the error message and backtrace.
227
+ Always check that the result indicates success before using the returned value.
228
+
229
+ ---
230
+
231
+ ## Workflow Pattern for Claude Code
232
+
233
+ 1. **Always start with `sketchup_status`** to confirm SketchUp is running.
234
+ 2. **Use `sketchup_inspect` for queries** (reading model state, inspecting geometry).
235
+ 3. **Use `sketchup_operation` for all writes** (adding/moving/deleting geometry) — makes changes undoable.
236
+ 4. **Use `sketchup_selection` to check** what the user has selected before acting on it.
237
+ 5. **Iterate small** — make one change, verify, then continue.
238
+ 6. **Screenshot-verify loop** — always visually confirm geometry changes using `sketchup_screenshot`:
239
+ - Set `eye` to a good vantage point for the geometry you changed
240
+ - Set `target` to the center of the area of interest
241
+ - The tool returns the image directly — just view it
242
+ 7. If the user says "undo", tell them to press Ctrl+Z in SketchUp (you can't programmatically undo via the bridge).
243
+
244
+ ---
245
+
246
+ ## Additional Notes
247
+
248
+ - `Sketchup.undo` works via inspect for quick rollbacks during iteration
249
+ - Entity indices change after any add/delete — never cache indices across operations
250
+ - All SketchUp internal units are inches
251
+ - Use `.to_l` for human-readable output (e.g., `84.0.to_l` → `7'`)
252
+
253
+ ## See Also
254
+ - `sketchup-building-framing`: Parametric framing with real lumber dimensions
255
+ - `sketchup-3d-warehouse-wrangling`: Placing/trimming 3D Warehouse components
@@ -0,0 +1,134 @@
1
+ ---
2
+ name: sketchup-building-model-geometry
3
+ description: |
4
+ Build geometry in SketchUp with visual verification at every step. Use when:
5
+ (1) creating boxes, walls, roofs, or any 3D shapes, (2) using pushpull or
6
+ extrusions that can go the wrong direction, (3) assembling multiple groups
7
+ into a structure, (4) any geometry creation where the result needs to look
8
+ correct from all angles. Enforces multi-angle screenshot verification and
9
+ a final model audit before declaring work complete.
10
+ author: MakeIt4Me
11
+ version: 2.0.0
12
+ date: 2026-03-15
13
+ ---
14
+
15
+ # Building Model Geometry
16
+
17
+ ## The Problem
18
+
19
+ When building geometry in SketchUp via the bridge, several things go wrong silently:
20
+
21
+ - **pushpull goes the wrong direction** — SketchUp's `face.pushpull` direction is non-deterministic. It depends on face normal orientation, which varies based on vertex winding order. A wall that should extrude outward extrudes inward. You can't tell from a single screenshot angle.
22
+ - **Groups clip into each other** — Two groups positioned at the same coordinates overlap. Looks fine from one angle, broken from another.
23
+ - **Geometry lands in the wrong spot** — Off-by-one in coordinate math puts a wall 3.5" too far left. Only visible from the side or top.
24
+ - **Faces are reversed** — The back material shows instead of the front. Invisible from most angles.
25
+
26
+ All of these look correct from at least one camera angle. The fix is to never trust a single screenshot.
27
+
28
+ ## Rules
29
+
30
+ ### 1. Verify after every geometry operation
31
+
32
+ After every `sketchup_operation` call that creates or moves geometry, take a screenshot with `sketchup_screenshot` and visually inspect it before moving on. Do not batch multiple operations and check once at the end.
33
+
34
+ ### 2. Use multiple camera angles
35
+
36
+ Never verify from a single angle. After creating geometry, check from at least two of these views using `sketchup_screenshot`:
37
+
38
+ **Front-right isometric** (default good starting point):
39
+ - eye: [200, -150, 120], target: [60, 60, 40]
40
+
41
+ **Back-left isometric** (catches reversed extrusions):
42
+ - eye: [-100, 200, 120], target: [60, 60, 40]
43
+
44
+ **Top-down** (catches X/Y positioning errors):
45
+ - eye: [60, 60, 300], target: [60, 60, 0]
46
+
47
+ **Front elevation** (catches Z errors, height issues):
48
+ - eye: [60, -200, 60], target: [60, 0, 60]
49
+
50
+ **Side elevation** (catches depth/Y errors):
51
+ - eye: [-200, 60, 60], target: [0, 60, 60]
52
+
53
+ Adjust the target point to center on the geometry you just created. The eye distance should be far enough to see the full context.
54
+
55
+ **Tip:** Use `orthographic: true` for elevation views. It removes perspective distortion, making it easier to see which parts are in front of or behind others and to verify alignment.
56
+
57
+ ### 3. Fix pushpull direction immediately
58
+
59
+ If a pushpull went the wrong way:
60
+ 1. Undo it (`Sketchup.undo` via `sketchup_inspect`)
61
+ 2. Reverse the face normal first, then pushpull again
62
+ 3. Or use negative distance: `face.pushpull(-distance)`
63
+
64
+ ```ruby
65
+ # Check which way the normal points before pushpull
66
+ normal = face.normal
67
+ # If normal.z < 0 for a floor face, reverse it first
68
+ face.reverse! if normal.z < 0
69
+ face.pushpull(height)
70
+ ```
71
+
72
+ ### 4. Name every group
73
+
74
+ Always name groups immediately after creation. This makes auditing and debugging possible:
75
+
76
+ ```ruby
77
+ grp = model.entities.add_group
78
+ grp.name = "Front Wall"
79
+ ```
80
+
81
+ ### 5. Check bounding boxes after placement
82
+
83
+ After positioning a group, verify its bounds make sense:
84
+
85
+ ```ruby
86
+ bb = grp.bounds
87
+ "#{grp.name}: min=#{bb.min}, max=#{bb.max}, size=#{bb.width.to_l} x #{bb.height.to_l} x #{bb.depth.to_l}"
88
+ ```
89
+
90
+ ### 6. Run model audit when you think you're done
91
+
92
+ Before telling the user the geometry is complete, run the `sketchup-model-auditing` checks:
93
+
94
+ - Check all groups are manifold solids (`group.manifold?`)
95
+ - Check for floating pieces (groups not resting on anything)
96
+ - Check for mesh intersections between groups
97
+ - Take a final multi-angle screenshot set
98
+
99
+ Do not declare work complete until the audit passes or you've explained any remaining issues to the user.
100
+
101
+ ## Screenshot Workflow
102
+
103
+ Use `sketchup_screenshot` after every geometry change. The tool returns the image directly — just view the result.
104
+
105
+ **Angle 1: front-right iso**
106
+ - eye: [200, -150, 120], target: [60, 60, 40]
107
+
108
+ **Angle 2: back-left iso**
109
+ - eye: [-100, 200, 120], target: [60, 60, 40]
110
+
111
+ Then check:
112
+ - Does the new geometry appear where expected?
113
+ - Is the extrusion direction correct?
114
+ - Are there any visible clipping or overlap issues?
115
+ - Do proportions look right relative to existing geometry?
116
+
117
+ ## Common Pitfalls
118
+
119
+ ### pushpull is not deterministic
120
+ The direction depends on face normal, which depends on vertex order. Always check the result visually. If it went wrong, undo and try `face.pushpull(-distance)` or `face.reverse!` first.
121
+
122
+ ### add_face vertex winding matters
123
+ Counter-clockwise vertices (viewed from outside) produce an outward-facing normal. Clockwise produces inward. When building walls, think about which side is "outside."
124
+
125
+ ### Coordinate system
126
+ SketchUp uses inches internally. X = width (left/right), Y = depth (front/back), Z = height (up/down). The origin (0,0,0) is the front-left corner at ground level.
127
+
128
+ ### Group transforms
129
+ When you add geometry inside a group, coordinates are relative to the group's local origin. If you need world coordinates, use `group.transformation` to convert.
130
+
131
+ ## See Also
132
+ - `sketchup-bridge`: Core MCP tools and Ruby API reference
133
+ - `sketchup-model-auditing`: Detailed geometry and structural auditing
134
+ - `sketchup-review-design`: Architectural review process
@@ -0,0 +1,160 @@
1
+ ---
2
+ name: sketchup-model-auditing
3
+ description: |
4
+ Programmatic geometry and structural auditing for SketchUp models via Ruby API.
5
+ Use when: (1) checking if framing groups are manifold solids, (2) detecting
6
+ floating/unsupported pieces, (3) finding mesh intersections between framing members,
7
+ (4) verifying sloped wall plates sit on stud tops, (5) AABB intersection checks
8
+ produce false positives on sloped geometry (rafters, roofs). Covers Solid Inspector 2
9
+ API integration, slope-aware collision detection, and structural connectivity checks.
10
+ author: Claude Code
11
+ version: 1.0.0
12
+ date: 2026-03-11
13
+ ---
14
+
15
+ # SketchUp Model Auditing
16
+
17
+ ## Problem
18
+ SketchUp's built-in tools (Solid Inspector², CleanUp³) only check individual geometry
19
+ validity (manifold, stray edges, reversed faces). They cannot detect:
20
+ - Pieces floating in space with nothing supporting them
21
+ - Mesh intersections between separate groups (studs through rafters, headers through kings)
22
+ - Structural connectivity issues (plates not seated on studs)
23
+
24
+ Additionally, naive axis-aligned bounding box (AABB) intersection checks produce massive
25
+ false positives on sloped geometry like rafters.
26
+
27
+ ## Context / Trigger Conditions
28
+ - After generating framing via build scripts
29
+ - When the visual screenshot shows floating or intersecting pieces
30
+ - When Solid Inspector says "all good" but the model clearly has problems
31
+ - When AABB checks report hundreds of "intersections" that aren't real
32
+
33
+ ## Solution
34
+
35
+ ### 1. Solid Inspector 2 API (geometry-only checks)
36
+ ```ruby
37
+ # Check manifold
38
+ group.manifold?
39
+
40
+ # Shell API for reversed/internal faces
41
+ shell = TT::Plugins::SolidInspector2::Shell.new(group)
42
+ shell.reversed_faces # => array of faces
43
+ shell.internal_faces # => array of faces
44
+
45
+ # Note: ErrorFinder.find_errors expects different args than you'd think
46
+ # Use Shell + manifold? instead for programmatic checks
47
+ ```
48
+
49
+ **What SI2 catches:** holes, stray edges, reversed faces, internal faces, non-manifold
50
+ **What SI2 misses:** floating pieces, spatial collisions, structural connectivity
51
+
52
+ ### 2. Floating Piece Detection
53
+ ```ruby
54
+ named_groups.each do |g|
55
+ bb = g.bounds
56
+ bottom_z = bb.min.z
57
+ next if bottom_z <= slab_top_z # on the slab
58
+
59
+ has_support = named_groups.any? { |other|
60
+ next false if other == g
61
+ ob = other.bounds
62
+ # Use 1.5" tolerance for narrow contact areas (stud top to plate bottom)
63
+ z_touch = (ob.max.z - bottom_z).abs < 1.5
64
+ x_overlap = ob.min.x < (bb.max.x + 1) && ob.max.x > (bb.min.x - 1)
65
+ y_overlap = ob.min.y < (bb.max.y + 1) && ob.max.y > (bb.min.y - 1)
66
+ z_touch && x_overlap && y_overlap
67
+ }
68
+ # flag if no support found
69
+ end
70
+ ```
71
+
72
+ **Key insight:** Expand the XY overlap tolerance by ~1" for narrow members (studs/plates
73
+ on the same wall have very small contact areas that strict AABB misses).
74
+
75
+ ### 3. Slope-Aware Intersection Detection (critical)
76
+
77
+ **The problem:** A rafter spanning Y=-7..138 has an AABB Z range of 83..115. Every stud
78
+ with a top Z above 83 will "intersect" the rafter's bounding box, even though the actual
79
+ rafter geometry at that stud's Y position is well above the stud.
80
+
81
+ **The fix:** Calculate the actual roof bottom Z at each entity's Y position:
82
+
83
+ ```ruby
84
+ # Derive slope from actual rafter geometry
85
+ rafters = groups.select { |g| g.name =~ /Rafter/i }
86
+ r = rafters.first
87
+ verts = r.entities.grep(Sketchup::Edge).flat_map { |e|
88
+ [e.start.position, e.end.position]
89
+ }.uniq { |p| [p.x.round(2), p.y.round(2), p.z.round(2)] }
90
+
91
+ sorted = verts.sort_by(&:y)
92
+ front_bottom_z = sorted.first(2).map(&:z).min
93
+ back_bottom_z = sorted.last(2).map(&:z).min
94
+ front_y = sorted.first(2).map(&:y).min
95
+ back_y = sorted.last(2).map(&:y).max
96
+
97
+ # Lambda to get roof bottom Z at any Y
98
+ run = back_y - front_y
99
+ rise = front_bottom_z - back_bottom_z
100
+ roof_bottom_z = lambda { |y|
101
+ t = (y - front_y) / run
102
+ front_bottom_z - t * rise
103
+ }
104
+
105
+ # Now check each stud against the ACTUAL roof Z at its position
106
+ studs.each do |s|
107
+ center_y = (s.bounds.min.y + s.bounds.max.y) / 2.0
108
+ roof_z = roof_bottom_z.call(center_y)
109
+ if s.bounds.max.z > roof_z + 0.5 # 0.5" tolerance
110
+ # REAL intersection — flag it
111
+ end
112
+ end
113
+ ```
114
+
115
+ **Result:** Went from 196 false-positive "intersections" to 0 with this approach.
116
+
117
+ ### 4. Header-King Stud Overlap Check
118
+ Headers should span between king studs, not through them. Check with volumetric overlap:
119
+ ```ruby
120
+ headers.each do |h|
121
+ kings.each do |k|
122
+ ox = [0, [h.bounds.max.x, k.bounds.max.x].min - [h.bounds.min.x, k.bounds.min.x].max].max
123
+ oy = [0, [h.bounds.max.y, k.bounds.max.y].min - [h.bounds.min.y, k.bounds.min.y].max].max
124
+ oz = [0, [h.bounds.max.z, k.bounds.max.z].min - [h.bounds.min.z, k.bounds.min.z].max].max
125
+ vol = ox * oy * oz
126
+ # Flag if vol > 1.0 cubic inch
127
+ end
128
+ end
129
+ ```
130
+
131
+ ### 5. Sloped Wall Plate Connectivity
132
+ On sloped walls, top plates must sit on stud tops (gap < 0.25"):
133
+ ```ruby
134
+ plates.each do |p|
135
+ stud_y = p.bounds.max.y.round(0) # plate sits on the lower (max-Y) stud
136
+ stud_top = studs_by_y[stud_y]
137
+ gap = (p.bounds.min.z - stud_top).abs
138
+ # Flag if gap > 0.25"
139
+ end
140
+ ```
141
+
142
+ **Common bug:** Plates positioned one plate-thickness (1.5") too high. Caused by
143
+ calculating plate Z as `stud_top + plate_height` instead of just `stud_top`.
144
+
145
+ ## Verification
146
+ Run the complete audit by sending the audit script via `sketchup_inspect`. Since MCP
147
+ tools accept multi-line Ruby directly, you can paste the full audit script into the
148
+ `code` parameter. Expected output: `ALL CHECKS PASSED` with 7/7 checks green.
149
+
150
+ ## Notes
151
+ - 3D Warehouse components (doors, shingles) will always fail `manifold?` — warn, don't fail
152
+ - The floating check needs expanded XY tolerance for narrow framing members
153
+ - Corner plate overlaps (where two walls meet) are expected — don't flag those
154
+ - Entity indices change after any add/delete — never cache across operations
155
+ - This audit is complementary to the visual screenshot-verify loop, not a replacement
156
+
157
+ ## See Also
158
+ - `sketchup-bridge`: MCP tools and Ruby API reference
159
+ - `sketchup-building-framing`: Parametric framing generation
160
+ - `sketchup-review-design`: Visual/architectural review process