spatial-placement is a skill from the Summer skill library: a guide your AI agent reads when the task matches, so it builds the good version on the first try. Place 3D objects and modular kit pieces from measured geometry: floors, walls, facades, pipes, alcoves.
When your agent uses it
- Positioning a prop, character, collider, or platform so it sits flush, avoids overlap, or keeps clearance
- Placing something against a wall, inside an alcove, or on a shelf and needing to know which side is blocked and by how much
- Repairing an overlap or a floating object after a placement
- Post-placement checks on a rotated prop using its own local axes
- Placing modular kit pieces — facade or wall modules edge to edge, storeys stacked, pipes, gutters and lamps on a wall, clamps along a pipe
- Measuring a kit piece’s size, origin and which way it faces before placing it
- Checking that a facade line is flush, with no gaps and no module standing proud
Install
summer setup installs every skill for your agent. To add only this one:
claude-code for your agent, such as codex or cursor. See Skills for every option.
The skill
Place from measured geometry, never from guesses about size or facing. Use Starcast as spatial evidence, not as an automatic placement solver. Make a reasonable transform from scene intent, inspect the result, then correct only the axes that the evidence shows are wrong. Every tool below is already shipped. Arguments, result shapes, limits and the engine ops behind them: references/kit-placement-tools.md.Choose the tool
Placement loop
- Call
summer_get_scene_treeand inspect the subject and intended anchor. Never guess paths, transforms, or dimensions. - Place the subject approximately with
summer_set_proporsummer_batch. - Call
summer_starcast(scenePath, path, detail="summary"). - Correct position or rotation from the smallest relevant set of facts.
- Call summary again. Stop when the intended support/contact and clearances are satisfied. Do not keep recasting a placement that already meets the brief.
detail="full" only when summary identifies an ambiguous blocker, several
nearby candidates, or a complex overlap. Full output is capped at 12 KB and may
return summary automatically. Keep directionSpace="world" unless placement is
defined relative to a rotated subject; then use directionSpace="local".
Read the result
subject.positionandsubject.sizedescribe the queried object.grounded: truemeans downward support was detected. It does not mean the object is centered or otherwise well placed.contactStatusandcontactsidentify touching or overlapping colliders. The physics shape query cannot distinguish touching from penetration here.directions.<label>.statusisblockedwhen clearance is below the tool’s threshold;distanceis measured from the subject bounds.evidence: "physics"is exact collider-query evidence.evidence: "visual_aabb"includes visible meshes without colliders, but is a world-axis-aligned broad-phase approximation. Do not infer exact surface contact from it.- Warnings about missing collision shapes or visual bounds mean coverage is partial; state that limitation rather than inventing certainty.
Modular kit placement
summer_inspect_assetevery piece type once and read itssummaryfirst: size, where the origin sits (origin.label), the two largest opposite plane pairs (a large+zplane at the max z offset means the visible face looks along +z and the back is-z; aone_sidedsheet with no opposite plane is invisible from behind), port-like loops (pipe and duct ends), anchors and colliders. Read the kit’s own notes too, but trust the measurement.summer_world_snapshot; keep thesnapshot_id.- Place the first piece of a line with
summer_instantiate_sceneand itsposition/rotation_degrees. Place the rest relative to it:summer_place_adjacentalong the line, again alongyfor the next storey. For many pieces at known poses use onesummer_batchwithreceipt: "summary". - Mount wall pieces with
summer_attach_to_surface, using the back axis from step 1. Instance each at its mount height first: the tool keeps the height and pushes the piece’s back face onto the wall, and refuses (putting the piece back) when the seat lands on another node. Join pipe and duct runs withsummer_connect_ports; itsother_portssays where a bend’s free end now points. Add clamps and braces withsummer_repeat_along. - Check:
summer_measureplane mode on each facade line (every front on one plane), pair mode on joints you doubt,summer_starcastwithdirectionSpace: "local"on mounted pieces,summer_test_placementbefore committing a piece in a tight spot. Starcast’s local names follow the engine:forwardis -Z,backis +Z. A piece with a -Z back should readforwardblocked by the wall at about the standoff (or the wall incontactswhen flush) andbackopen. summer_snapshot_diffagainst the id from step 2, thensummer_screenshotand look at it. Fix facing from the measurement, not by eye.
Worked example: two-storey facade wall with a downpipe and a lamp
Pieces (measured in step 1):wall_double is 2 x 3 x 0.2 m, origin bottom
centre, front +z; window_double the same size; gutter_section is 1 m tall
with its back -z and open loops at both ends; wall_lamp has its back -z;
wall_clamp is small with its back -z. Scene res://facade_test.tscn with a
Facade Node3D at the origin.
Place every piece at a rough pose in one summer_batch, then let the measured
tools seat each one:
open_loops in step 1 (its
summary.port_like_loops): +Y is the outermost loop facing +Y in the
piece’s own axes (here the top end), -Y the bottom; a second loop facing the
same way is +Y#2. The ids do not depend on radius or pose.
On the target pick the loop whose direction points where the run continues;
on the subject, the one that points back at the target. A join that would tilt
the piece more than 5 degrees is refused and lists the ports that fit; pass
allowTilt: true only for an intended tilt. With kits that ship Marker3D
anchors, pass their names instead.
Placement recipes
- Floor/platform: require downward support, no unintended contacts, and open movement/access directions. Correct vertical position first.
- Shelf: require shelf support, no back/side overlap, and enough forward clearance to remain visible and reachable.
- Wall: use the intended horizontal direction as the anchor, preserve a small gap unless contact is requested, and verify the opposite side is open.
- Alcove: check back, both sides, up, down, and relevant diagonals. Request full only if summary cannot identify which surface blocks the subject.
- Rotated object: use local directions only when “front”, “side”, or “up” refers to the object’s orientation; use world directions for level axes.
- Overlap repair: move along the clearest axis with the shortest correction, then rerun. Do not resize the asset unless the user asked for that.
- Facade line: modules edge to edge with
summer_place_adjacent(alignOtherAxes{y: "min", z: "max"}for a +z front), thensummer_measureplane mode on the fronts. A module reportedproudorrecessedis moved along the face axis by itsdeviation. - Pipes and gutters: back on the wall’s front plane (
summer_attach_to_surfacewith the measured back axis), runs joined withsummer_connect_ports, clamps withsummer_repeat_along. Starcast in local space: the back-axis direction (forwardfor a -Z back) blocked at about the standoff. - Wall fixtures (lamps, AC units, signs):
summer_raycastto find the wall point,summer_test_placementif the spot is crowded, thensummer_attach_to_surface.
Guardrails
- Always provide exact
scenePathandpath; selection fallback is not deterministic agent behavior. - Starcast is read-only and never moves or saves the subject.
- One representative ray per direction can miss off-center geometry. Combine directional results with contacts, nearby evidence, hierarchy, and rendered verification for high-consequence placements.
- Cameras, lights, audio, navigation nodes, scripts, and plain Nodes are not obstacles unless they own collision or renderable geometry.
- Prefer two useful summary calls around one correction over repeated full calls.
- Never infer a piece’s facing from its file name or a screenshot alone.
Measure it (
summer_inspect_asset), place it, then confirm with Starcast (local) and a screenshot. - Batch receipts over a few ops: always
receipt: "summary". visual_aabbmeasurements (measure, place_adjacent) are box bounds: an overhang or a lip sets the face. Say so when it matters.- A piece seated flush against a single-sided wall can read
openin the wall’s direction whilecontactslists the wall: Starcast’s one ray per direction starts at the touching face. Readcontactstoo.
From a shell
No Summer MCP tools in this session? Run each one as a command; whensummer --version is missing or below 4.0, use npx -y summer-engine@latest in place of summer. Fields are flags in kebab-case (--scene-path res://main.tscn) or one --input '<json>', and summer ops describe <op> prints the exact input. The summer-cli skill has the rest.
Files in this skill
Related skills
world-building-3d: Compose, ground and space 3D scenes with Summer’s four spatial tools, one geometric decision at a time.scene-composition: Scene structure: node hierarchy, when to extract sub-scenes, reusable prefabs, instance vs add node.
Source:
library/skills/spatial-placement/SKILL.md, rendered from summer-engine@4.3.0 on npm.
