Agent Collective Intelligence Coordinator
ruvnet/ruflo
Agent skill for collective-intelligence-coordinator - invoke with $agent-collective-intelligence-coordinator
CesiumJS primitives and geometry - Primitive, GeometryInstance, Appearance, BufferPrimitive collections, GeoJsonPrimitive, Billboard/Label/PointPrimitive collections, built-in geometry shapes…
$ npx skills add CesiumGS/cesiumjs-skills --skill cesiumjs-primitives -a claude-codeProject install by default; add -g for ~/.claude/skills/.
$ gh skill install CesiumGS/cesiumjs-skills cesiumjs-primitives --agent claude-codeProject scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).
$ git clone --depth 1 https://github.com/CesiumGS/cesiumjs-skills.git skills-src && mkdir -p .claude/skills && cp -r skills-src/skills/cesiumjs-primitives .claude/skills/cesiumjs-primitives && rm -rf skills-srcUse ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.
Claude Code skills documentation · loads skills from .claude/skills/
Install the "cesiumjs-primitives" agent skill from https://github.com/CesiumGS/cesiumjs-skills/tree/main/skills/cesiumjs-primitives into .claude/skills/cesiumjs-primitives/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "cesiumjs-primitives", then confirm the skill loads.Claude Code copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$skill-installer install https://github.com/CesiumGS/cesiumjs-skills/tree/main/skills/cesiumjs-primitivesType this inside Codex. $skill-installer <name> installs a curated skill from openai/skills. The installer writes to $CODEX_HOME/skills (default ~/.codex/skills). Restart Codex if the skill does not show up.
$ npx skills add CesiumGS/cesiumjs-skills --skill cesiumjs-primitives -a codexProject install goes to .agents/skills/; add -g for ~/.codex/skills/.
$ gh skill install CesiumGS/cesiumjs-skills cesiumjs-primitives --agent codexProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/CesiumGS/cesiumjs-skills.git skills-src && mkdir -p .agents/skills && cp -r skills-src/skills/cesiumjs-primitives .agents/skills/cesiumjs-primitives && rm -rf skills-srcUse ~/.agents/skills/ instead of .agents/skills for a personal install.
Codex skills documentation · loads skills from .agents/skills/
Install the "cesiumjs-primitives" agent skill from https://github.com/CesiumGS/cesiumjs-skills/tree/main/skills/cesiumjs-primitives into .agents/skills/cesiumjs-primitives/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "cesiumjs-primitives", then confirm the skill loads.Codex copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add CesiumGS/cesiumjs-skills --skill cesiumjs-primitives -a cursorProject install goes to .agents/skills/; add -g for ~/.cursor/skills/.
$ gh skill install CesiumGS/cesiumjs-skills cesiumjs-primitives --agent cursorProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/CesiumGS/cesiumjs-skills.git skills-src && mkdir -p .cursor/skills && cp -r skills-src/skills/cesiumjs-primitives .cursor/skills/cesiumjs-primitives && rm -rf skills-srcUse ~/.cursor/skills/ instead of .cursor/skills for a personal install.
Cursor skills documentation · loads skills from .cursor/skills/, .agents/skills/, .claude/skills/, .codex/skills/
Install the "cesiumjs-primitives" agent skill from https://github.com/CesiumGS/cesiumjs-skills/tree/main/skills/cesiumjs-primitives into .cursor/skills/cesiumjs-primitives/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "cesiumjs-primitives", then confirm the skill loads.Cursor copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gemini skills install https://github.com/CesiumGS/cesiumjs-skills.git --path skills/cesiumjs-primitives--scope user (default) or --scope workspace; --path is the subfolder of the repo that holds the skill; --consent skips the security confirmation prompt.
$ npx skills add CesiumGS/cesiumjs-skills --skill cesiumjs-primitives -a gemini-cliProject install goes to .agents/skills/; add -g for ~/.gemini/skills/.
$ gh skill install CesiumGS/cesiumjs-skills cesiumjs-primitives --agent gemini-cliProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/CesiumGS/cesiumjs-skills.git skills-src && mkdir -p .gemini/skills && cp -r skills-src/skills/cesiumjs-primitives .gemini/skills/cesiumjs-primitives && rm -rf skills-srcUse ~/.gemini/skills/ instead of .gemini/skills for a personal install, then run /skills reload.
Gemini CLI skills documentation · loads skills from .gemini/skills/, .agents/skills/
Install the "cesiumjs-primitives" agent skill from https://github.com/CesiumGS/cesiumjs-skills/tree/main/skills/cesiumjs-primitives into .gemini/skills/cesiumjs-primitives/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "cesiumjs-primitives", then confirm the skill loads.Gemini CLI copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gh skill install CesiumGS/cesiumjs-skills cesiumjs-primitivesInstalls for Copilot at project scope by default; add --scope user for a personal install. Preview a skill first with gh skill preview. Needs GitHub CLI 2.90.0 or later (public preview).
$ npx skills add CesiumGS/cesiumjs-skills --skill cesiumjs-primitives -a github-copilotProject install goes to .agents/skills/; add -g for ~/.copilot/skills/.
$ git clone --depth 1 https://github.com/CesiumGS/cesiumjs-skills.git skills-src && mkdir -p .github/skills && cp -r skills-src/skills/cesiumjs-primitives .github/skills/cesiumjs-primitives && rm -rf skills-srcUse ~/.copilot/skills/ instead of .github/skills for a personal install. Commit .github/skills so cloud agent and code review can use it.
GitHub Copilot skills documentation · loads skills from .github/skills/, .claude/skills/, .agents/skills/
Install the "cesiumjs-primitives" agent skill from https://github.com/CesiumGS/cesiumjs-skills/tree/main/skills/cesiumjs-primitives into .github/skills/cesiumjs-primitives/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "cesiumjs-primitives", then confirm the skill loads.GitHub Copilot copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add CesiumGS/cesiumjs-skills --skill cesiumjs-primitives -a opencodeOpenCode documents no install command of its own. Project install goes to .agents/skills/; add -g for ~/.config/opencode/skills/.
$ gh skill install CesiumGS/cesiumjs-skills cesiumjs-primitives --agent opencodeProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/CesiumGS/cesiumjs-skills.git skills-src && mkdir -p .opencode/skills && cp -r skills-src/skills/cesiumjs-primitives .opencode/skills/cesiumjs-primitives && rm -rf skills-srcUse ~/.config/opencode/skills/ instead of .opencode/skills for a personal install.
OpenCode skills documentation · loads skills from .opencode/skills/, .claude/skills/, .agents/skills/
Install the "cesiumjs-primitives" agent skill from https://github.com/CesiumGS/cesiumjs-skills/tree/main/skills/cesiumjs-primitives into .opencode/skills/cesiumjs-primitives/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "cesiumjs-primitives", then confirm the skill loads.OpenCode copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
cesiumjs-primitivesCesiumJS primitives and geometry - Primitive, GeometryInstance, Appearance, BufferPrimitive collections, GeoJsonPrimitive, Billboard/Label/PointPrimitive collections, built-in geometry shapes…
Cesiumjs Primitives is an agent skill from CesiumGS/cesiumjs-skills. CesiumJS primitives and geometry - Primitive, GeometryInstance, Appearance, BufferPrimitive collections, GeoJsonPrimitive, Billboard/Label/PointPrimitive collections, built-in geometry shapes, ground primitives, classification. Use when rendering performance-critical static or vector geometry, loading GeoJSON without entities, creating custom shapes, batching draw calls, or using low-level collections.
Its SKILL.md is about 7k tokens, which your agent loads only when the skill is triggered. It is a single SKILL.md file with no bundled scripts.
The repository describes itself as: Curated agent skills for CesiumJS development. The licence is Apache-2.0.
12 steps, taken from the first numbered list in SKILL.md.
Read from SKILL.md and the folder at commit 5f4792c. It shows what the files ask for, not the result of running them.
Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.
From allowed-tools in the SKILL.md frontmatter.
No scripts in the folder and no shell commands in SKILL.md (its code samples are javascript).
From the folder's file list and the shell code blocks in SKILL.md.
No URLs in SKILL.md.
From URLs in SKILL.md, links to its own repository left out.
Names no API keys, tokens, secrets or passwords.
From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.
Cesiumjs Primitives loads about 7k tokens when it runs. Until then it costs about 106 tokens; SKILL.md has 1,494 words of instructions outside code blocks.
Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.
The automated check found no risky patterns in SKILL.md.
Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.
The full file from CesiumGS/cesiumjs-skills at commit 5f4792c, republished under its Apache-2.0 licence (© CesiumGS). 1,494 words, ~7,034 tokens.
.claude/skills/cesiumjs-primitives/SKILL.md (or your agent's skills folder).Applies to: CesiumJS v1.144+ (ES module imports,
??instead ofdefaultValue)
The Primitive API is the low-level rendering layer beneath the Entity API, trading convenience for performance.
Core formula: Primitive = GeometryInstance[] + Appearance
Primitives are immutable after first render -- geometry cannot change, but per-instance attributes update via primitive.getGeometryInstanceAttributes(id).
import {
Viewer, Primitive, GeometryInstance, EllipseGeometry,
EllipsoidSurfaceAppearance, Material, Cartesian3, Math as CesiumMath,
} from "cesium";
const viewer = new Viewer("cesiumContainer");
const scene = viewer.scene;
const primitive = scene.primitives.add(new Primitive({
geometryInstances: new GeometryInstance({
geometry: new EllipseGeometry({
center: Cartesian3.fromDegrees(-100.0, 40.0),
semiMinorAxis: 250000.0,
semiMajorAxis: 400000.0,
rotation: CesiumMath.PI_OVER_FOUR,
vertexFormat: EllipsoidSurfaceAppearance.VERTEX_FORMAT, // must match appearance
}),
id: "myEllipse", // returned by Scene.pick()
}),
appearance: new EllipsoidSurfaceAppearance({ material: Material.fromType("Stripe") }),
}));| Option | Default | Purpose |
|---|---|---|
geometryInstances | -- | Single instance or array |
appearance | -- | Shading (Appearance subclass) |
show | true | Toggle visibility |
modelMatrix | Matrix4.IDENTITY | Transform all instances |
asynchronous | true | Build geometry on web worker |
releaseGeometryInstances | true | Free geometry after GPU upload |
allowPicking | true | false saves GPU memory |
shadows | ShadowMode.DISABLED | Cast/receive shadows |
All instances in one Primitive share a single draw call.
import {
Primitive, GeometryInstance, RectangleGeometry, EllipseGeometry,
PerInstanceColorAppearance, ColorGeometryInstanceAttribute,
Cartesian3, Rectangle, Color,
} from "cesium";
scene.primitives.add(new Primitive({
geometryInstances: [
new GeometryInstance({
geometry: new RectangleGeometry({
rectangle: Rectangle.fromDegrees(-140, 30, -100, 40),
vertexFormat: PerInstanceColorAppearance.VERTEX_FORMAT,
}),
id: "rect",
attributes: { color: ColorGeometryInstanceAttribute.fromColor(Color.RED.withAlpha(0.5)) },
}),
new GeometryInstance({
geometry: new EllipseGeometry({
center: Cartesian3.fromDegrees(-80, 35),
semiMinorAxis: 200000.0,
semiMajorAxis: 300000.0,
vertexFormat: PerInstanceColorAppearance.VERTEX_FORMAT,
}),
id: "ellipse",
attributes: { color: ColorGeometryInstanceAttribute.fromColor(Color.BLUE.withAlpha(0.5)) },
}),
],
appearance: new PerInstanceColorAppearance(),
}));Volume geometry (Cylinder, Box, Ellipsoid) must be positioned via modelMatrix on each GeometryInstance. Use Matrix4.multiply to combine a world-space anchor with a local offset, then batch all instances into one Primitive.
import {
Primitive, GeometryInstance, CylinderGeometry,
PerInstanceColorAppearance, ColorGeometryInstanceAttribute,
Cartesian3, Matrix4, Transforms, Color, Math as CesiumMath,
} from "cesium";
const center = Cartesian3.fromDegrees(-73.9857, 40.7580);
const anchorFrame = Transforms.eastNorthUpToFixedFrame(center, undefined, new Matrix4());
const instances = [];
const GRID = 10;
const SPACING = 50; // metres
for (let row = 0; row < GRID; row++) {
for (let col = 0; col < GRID; col++) {
const xOffset = (col - GRID / 2) * SPACING;
const yOffset = (row - GRID / 2) * SPACING;
// Combine anchor ENU frame with a local XYZ offset
const modelMatrix = Matrix4.multiply(
anchorFrame,
Matrix4.fromTranslation(new Cartesian3(xOffset, yOffset, 100), new Matrix4()),
new Matrix4(),
);
instances.push(new GeometryInstance({
geometry: new CylinderGeometry({
length: 200,
topRadius: 8,
bottomRadius: 8,
vertexFormat: PerInstanceColorAppearance.VERTEX_FORMAT,
}),
modelMatrix,
attributes: { color: ColorGeometryInstanceAttribute.fromColor(Color.fromRandom({ alpha: 1.0 })) },
}));
}
}
scene.primitives.add(new Primitive({
geometryInstances: instances,
appearance: new PerInstanceColorAppearance({ flat: true }),
}));
// Frame the grid so the full batch is visible -- a shallow pitch hides cylinders
// behind the foreground; a near-nadir pitch flattens them. Aim for ~-45° (-PI/4)
// at a range that covers the grid footprint (GRID * SPACING) with margin.
const range = GRID * SPACING * 3; // ~1500 m for a 10x10x50m grid
viewer.camera.lookAt(
center,
new Cartesian3(0, -range * 0.7, range * 0.7), // offset south + up for -45° pitch
);Key patterns:
Matrix4.multiply(anchorFrame, Matrix4.fromTranslation(offset, result), result) -- compose the ENU frame at a geographic anchor with a local East/North/Up translation.Color.fromRandom({ alpha: 1.0 }) produces fully-opaque random colours suitable for rainbow-coloured batches.~-45° (-CesiumMath.PI_OVER_FOUR, ~-0.785 rad) pitch at a range of roughly 3 * gridFootprint. Pitches shallower than ~-0.6 rad can push the grid off-screen or hide it behind buildings; nadir views flatten cylinders into dots and lose the batched "field" appearance. A -0.61 rad pitch is still shallow enough to leave the grid completely out of frame.primitive.ready, prefer viewer.camera.flyToBoundingSphere(primitive._boundingSpheres[0], { duration: 0 }) (or viewer.flyTo(primitive)) over hand-tuned offsets if the scenario only requires "the batch is visible".import { ColorGeometryInstanceAttribute, ShowGeometryInstanceAttribute } from "cesium";
// Wait for async geometry compilation
const removeListener = scene.postRender.addEventListener(() => {
if (!primitive.ready) return;
const attrs = primitive.getGeometryInstanceAttributes("rect");
attrs.color = ColorGeometryInstanceAttribute.toValue(Color.YELLOW);
attrs.show = ShowGeometryInstanceAttribute.toValue(true);
removeListener();
});Nestable container -- scene.primitives is itself a PrimitiveCollection.
import { PrimitiveCollection, BillboardCollection, LabelCollection } from "cesium";
const group = new PrimitiveCollection();
group.add(new BillboardCollection());
group.add(new LabelCollection());
scene.primitives.add(group);
group.show = false; // toggle all children| Need | Use |
|---|---|
| Entity lifecycle, clustering, per-entity styling, time-dynamic values | GeoJsonDataSource in cesiumjs-entities |
| One large GeoJSON object with low overhead and primitive-level performance | GeoJsonPrimitive in this skill |
| Tiled vector data, 3D Tiles LOD, metadata styling, feature picking | MVTDataProvider in cesiumjs-3d-tiles |
| Fully manual high-throughput point/polyline/polygon buffers | BufferPointCollection, BufferPolylineCollection, BufferPolygonCollection |
Use BufferPointCollection, BufferPolylineCollection, and BufferPolygonCollection
for very large vector datasets where Entity/DataSource overhead is too high. These
APIs were introduced in 1.140 (#13212) and refined through 1.142; they are
experimental and use flyweight primitive objects: reuse one BufferPoint,
BufferPolyline, or BufferPolygon when adding or iterating thousands of items.
import {
BlendOption,
BoundingSphere,
BufferPoint,
BufferPointCollection,
BufferPointMaterial,
Cartesian3,
Color,
} from "cesium";
const positions = [
Cartesian3.fromDegrees(-75.16, 39.95),
Cartesian3.fromDegrees(-73.98, 40.75),
];
const points = scene.primitives.add(new BufferPointCollection({
primitiveCountMax: positions.length,
allowPicking: true,
blendOption: BlendOption.TRANSLUCENT,
boundingVolume: BoundingSphere.fromPoints(positions), // world space in 1.142+
}));
const point = new BufferPoint();
const material = new BufferPointMaterial({
color: Color.CYAN.withAlpha(0.65),
outlineColor: Color.WHITE.withAlpha(0.9),
outlineWidth: 2,
size: 10,
});
positions.forEach((position, featureId) => {
points.add({
position,
featureId,
material,
}, point);
});
const picked = scene.pick(windowPosition);
if (picked?.collection === points) {
console.log(picked.index, picked.primitive.featureId);
}Breaking change (1.141, #13448):
BufferPrimitiveCollection.modelMatrix,boundingVolume, andboundingVolumeWCare now readonly -- you may mutate the object in place, but reassigning the property (collection.modelMatrix = ...) throws. Update the existing matrix/volume instead of swapping in a new one.
1.142 notes:
boundingVolume is now world-space, not local/model-space. If you provide it manually, include the collection modelMatrix transform yourself.boundingVolume skips automatic recomputation; this helps large animated collections but makes you responsible for keeping the volume valid.blendOption is supported on all three buffer collections and enables alpha from BufferPrimitiveMaterial#color; BufferPointCollection also honors outlineColor.alpha.BlendOption.OPAQUE only when every material is fully opaque; use TRANSLUCENT or mixed blending when alpha varies.In 1.143, BufferPointCollection no longer leaks outlineColor into the fill
when outlineWidth is 0. Set the width to 0 to disable outlines; remove
transparent-outline workarounds that would otherwise complicate batching.
GeoJsonPrimitive loads GeoJSON directly into buffer primitive collections,
bypassing GeoJsonDataSource and the Entity layer. Prefer it for large static
or bulk-updated vector datasets. Keep using GeoJsonDataSource when you need
Entity conveniences, time-dynamic properties, clustering, or DataSource lifecycle
integration.
import { GeoJsonPrimitive } from "cesium";
const counties = await GeoJsonPrimitive.fromUrl("/data/counties.geojson", {
allowPicking: true,
});
scene.primitives.add(counties);
console.log(counties.featureCount);
console.log(counties.points); // BufferPointCollection | undefined
console.log(counties.polylines); // BufferPolylineCollection | undefined
console.log(counties.polygons); // BufferPolygonCollection | undefined
// Picking returns the GeoJsonPrimitive pick object, including source properties.
const picked = scene.pick(windowPosition);
if (picked?.parentPrimitive === counties) {
const featureId = picked.primitive.featureId;
console.log(counties.getId(featureId));
console.log(counties.getProperties(featureId));
}GeoJsonPrimitive.fromGeoJson(parsedObject) is available when the GeoJSON is
already in memory. Source feature IDs are exposed through ids/getId(), and
source properties through properties/getProperties().
All geometries take shape parameters and a vertexFormat matching the Appearance. Most have a paired *OutlineGeometry. Outlines require a separate Primitive.
import {
Primitive, GeometryInstance, PolygonGeometry, PolygonOutlineGeometry,
PolygonHierarchy, PerInstanceColorAppearance, ColorGeometryInstanceAttribute,
Cartesian3, Color,
} from "cesium";
const positions = Cartesian3.fromDegreesArray([-115, 37, -115, 32, -107, 33, -102, 35]);
// Fill primitive
scene.primitives.add(new Primitive({
geometryInstances: new GeometryInstance({
geometry: new PolygonGeometry({
polygonHierarchy: new PolygonHierarchy(positions),
vertexFormat: PerInstanceColorAppearance.VERTEX_FORMAT,
}),
attributes: { color: ColorGeometryInstanceAttribute.fromColor(Color.CYAN.withAlpha(0.5)) },
}),
appearance: new PerInstanceColorAppearance(),
}));
// Outline primitive (separate draw call)
scene.primitives.add(new Primitive({
geometryInstances: new GeometryInstance({
geometry: new PolygonOutlineGeometry({ polygonHierarchy: new PolygonHierarchy(positions) }),
attributes: { color: ColorGeometryInstanceAttribute.fromColor(Color.WHITE) },
}),
appearance: new PerInstanceColorAppearance({ flat: true }),
}));Every XxxGeometry has a matching XxxOutlineGeometry unless noted.
Surface (work with GroundPrimitive): CircleGeometry, CorridorGeometry, EllipseGeometry, PolygonGeometry, RectangleGeometry.
Volume (need modelMatrix): BoxGeometry (fromDimensions()), CylinderGeometry (cone when topRadius != bottomRadius), EllipsoidGeometry, SphereGeometry, FrustumGeometry, PlaneGeometry.
Path: CorridorGeometry (buffered path), PolylineVolumeGeometry (2D shape extruded along path), WallGeometry (vertical curtain).
Polygon: PolygonGeometry (holes via PolygonHierarchy), CoplanarPolygonGeometry (non-Earth-surface).
Line (no outline): PolylineGeometry (pixel-width), SimplePolylineGeometry (1px), GroundPolylineGeometry (GroundPolylinePrimitive only).
Box, Ellipsoid, Cylinder, and Frustum need a modelMatrix on the GeometryInstance.
import { GeometryInstance, BoxGeometry, PerInstanceColorAppearance,
ColorGeometryInstanceAttribute, Cartesian3, Matrix4, Transforms, Color } from "cesium";
const modelMatrix = Matrix4.multiplyByTranslation(
Transforms.eastNorthUpToFixedFrame(Cartesian3.fromDegrees(-105, 40)),
new Cartesian3(0, 0, 250000), new Matrix4(),
);
new GeometryInstance({
geometry: BoxGeometry.fromDimensions({
dimensions: new Cartesian3(400000, 300000, 500000),
vertexFormat: PerInstanceColorAppearance.VERTEX_FORMAT,
}),
modelMatrix,
id: "floatingBox",
attributes: { color: ColorGeometryInstanceAttribute.fromColor(Color.CORAL) },
});| Appearance | Use Case | Material? |
|---|---|---|
PerInstanceColorAppearance | Per-instance color | No |
MaterialAppearance | Arbitrary geometry + Material | Yes |
EllipsoidSurfaceAppearance | Surface geometry + Material (fewer attrs) | Yes |
PolylineColorAppearance | Per-instance color polylines | No |
PolylineMaterialAppearance | Polylines with Material | Yes |
DebugAppearance | Visualize vertex attributes | No |
Appearance | Base class / custom shaders | Optional |
The geometry vertexFormat must match the appearance. Use the appearance's static VERTEX_FORMAT. For PerInstanceColorAppearance without lighting, use FLAT_VERTEX_FORMAT.
import { Primitive, GeometryInstance, WallGeometry, MaterialAppearance, Material, Cartesian3 } from "cesium";
scene.primitives.add(new Primitive({
geometryInstances: new GeometryInstance({
geometry: new WallGeometry({
positions: Cartesian3.fromDegreesArrayHeights([-115, 44, 200000, -110, 44, 200000, -105, 44, 200000]),
vertexFormat: MaterialAppearance.MaterialSupport.TEXTURED.vertexFormat,
}),
}),
appearance: new MaterialAppearance({
material: Material.fromType("Checkerboard"),
faceForward: true, // shade both sides
}),
}));Drapes geometry onto terrain/3D Tiles. Supported: CircleGeometry, CorridorGeometry, EllipseGeometry, PolygonGeometry, RectangleGeometry. Add to scene.primitives (not scene.groundPrimitives -- both work but scene.primitives is the conventional target when using a public basemap without Ion terrain).
import { GroundPrimitive, GeometryInstance, PolygonGeometry, PolygonHierarchy,
PerInstanceColorAppearance, ColorGeometryInstanceAttribute, ClassificationType,
Cartesian3, Color } from "cesium";
scene.primitives.add(new GroundPrimitive({
geometryInstances: new GeometryInstance({
geometry: new PolygonGeometry({
polygonHierarchy: new PolygonHierarchy(
Cartesian3.fromDegreesArray([-112, 36, -112, 36.1, -111.9, 36.1]),
),
}),
id: "groundPolygon",
attributes: { color: ColorGeometryInstanceAttribute.fromColor(Color.RED.withAlpha(0.5)) },
}),
appearance: new PerInstanceColorAppearance({ flat: true, translucent: true }),
classificationType: ClassificationType.TERRAIN, // TERRAIN, CESIUM_3D_TILE, or BOTH
}));Drapes a polyline on terrain. Add to scene.primitives (not scene.groundPrimitives).
import { GroundPolylinePrimitive, GeometryInstance, GroundPolylineGeometry,
PolylineColorAppearance, ColorGeometryInstanceAttribute, Cartesian3, Color } from "cesium";
scene.primitives.add(new GroundPolylinePrimitive({
geometryInstances: new GeometryInstance({
geometry: new GroundPolylineGeometry({
positions: Cartesian3.fromDegreesArray([-112.13, 36.05, -112.09, 36.10, -112.13, 36.17]),
width: 4.0,
loop: true,
}),
attributes: { color: ColorGeometryInstanceAttribute.fromColor(Color.LIME.withAlpha(0.7)) },
}),
appearance: new PolylineColorAppearance(),
}));Highlights volumes classifying terrain or 3D Tiles. Valid: BoxGeometry, CylinderGeometry, EllipsoidGeometry, PolylineVolumeGeometry, SphereGeometry, plus extruded surface geometries.
import { ClassificationPrimitive, GeometryInstance, BoxGeometry, PerInstanceColorAppearance,
ColorGeometryInstanceAttribute, ClassificationType, Cartesian3, Transforms, Color } from "cesium";
scene.primitives.add(new ClassificationPrimitive({
geometryInstances: new GeometryInstance({
geometry: BoxGeometry.fromDimensions({
dimensions: new Cartesian3(100, 100, 50),
vertexFormat: PerInstanceColorAppearance.VERTEX_FORMAT,
}),
modelMatrix: Transforms.eastNorthUpToFixedFrame(Cartesian3.fromDegrees(-75.59, 40.04, 25)),
attributes: { color: ColorGeometryInstanceAttribute.fromColor(Color.YELLOW.withAlpha(0.5)) },
}),
classificationType: ClassificationType.BOTH,
}));GPU-efficient viewport-aligned images -- far more performant than entities at scale.
Breaking change (1.140, #13253):
BillboardCollectionandLabelCollectionnow require WebGL 2, or WebGL 1 withANGLE_instanced_arraysandMAX_VERTEX_TEXTURE_IMAGE_UNITS > 0. On unsupported devices they no longer render -- gate onscene.context.webgl2(or feature-detect the extension) if you still target legacy WebGL 1 hardware.
Compatibility fix (1.143): billboard image loading no longer crashes when an application replaces the global
Promiseimplementation. Use the publicimageproperty with a URL, loaded image, or canvas; usesetImagefor aResourceor callback. Do not branch on nativePromiseidentity or retain compatibility shims for this bug.
import { BillboardCollection, Cartesian3, Color, NearFarScalar,
HeightReference, HorizontalOrigin, VerticalOrigin } from "cesium";
const billboards = scene.primitives.add(new BillboardCollection({ scene }));
const b = billboards.add({
position: Cartesian3.fromDegrees(-75.59, 40.04),
image: "marker.png",
horizontalOrigin: HorizontalOrigin.CENTER,
verticalOrigin: VerticalOrigin.BOTTOM,
heightReference: HeightReference.CLAMP_TO_GROUND,
scaleByDistance: new NearFarScalar(1000, 1.5, 1e7, 0.3),
});
b.position = Cartesian3.fromDegrees(-75.60, 40.05); // update dynamically
billboards.remove(b);PinBuilder generates canvas-based pin icons at runtime without external image files. Use fromColor for solid-colour pins or fromText for labelled pins. Pass the returned canvas as the billboard image.
When a scenario specifies an ordered list of cities/items and a colour-by-index scheme, iterate the source array in the given order and use the loop index directly as the HSL hue index. Re-ordering the source list (e.g. sorting by latitude) swaps which colour lands on which city and fails visual checks.
import { BillboardCollection, PinBuilder, Cartesian3, Color, VerticalOrigin } from "cesium";
const pinBuilder = new PinBuilder();
const cities = [
{ name: "Boston", lng: -71.0589, lat: 42.3601 },
{ name: "New York", lng: -74.0060, lat: 40.7128 },
{ name: "Philadelphia", lng: -75.1652, lat: 39.9526 },
{ name: "Washington DC",lng: -77.0369, lat: 38.9072 },
{ name: "Miami", lng: -80.1918, lat: 25.7617 },
];
const billboards = scene.primitives.add(new BillboardCollection({ scene }));
cities.forEach((city, index) => {
billboards.add({
position: Cartesian3.fromDegrees(city.lng, city.lat),
// Color.fromHsl(hue 0-1, saturation, lightness) produces evenly-spaced hues
image: pinBuilder.fromColor(Color.fromHsl(index / cities.length, 0.8, 0.5), 48),
verticalOrigin: VerticalOrigin.BOTTOM,
});
});
// Text label pin: pinBuilder.fromText("A", Color.ROYALBLUE, 48)
// fromColor / fromText return a canvas -- pass directly as imageColor.fromHsl(hue, saturation, lightness) -- generates colours across the spectrum by varying hue (0–1 wraps full circle). Useful for rainbow-colouring N items: Color.fromHsl(i / n, 0.8, 0.5). Color.fromRandom({ alpha }) -- random hue/saturation/lightness with fixed alpha.
import { LabelCollection, Cartesian3, Cartesian2, Color, LabelStyle, VerticalOrigin } from "cesium";
const labels = scene.primitives.add(new LabelCollection({ scene }));
labels.add({
position: Cartesian3.fromDegrees(-75.59, 40.04, 300),
text: "Philadelphia",
font: "16px sans-serif",
fillColor: Color.WHITE,
outlineColor: Color.BLACK,
outlineWidth: 2,
style: LabelStyle.FILL_AND_OUTLINE,
verticalOrigin: VerticalOrigin.BOTTOM,
pixelOffset: new Cartesian2(0, -10),
});import { PointPrimitiveCollection, Cartesian3, Color, NearFarScalar } from "cesium";
const points = scene.primitives.add(new PointPrimitiveCollection());
points.add({
position: Cartesian3.fromDegrees(-75.59, 40.04),
pixelSize: 10,
color: Color.YELLOW,
outlineColor: Color.BLACK,
outlineWidth: 2,
scaleByDistance: new NearFarScalar(1000, 1.0, 1e7, 0.1),
});import { CloudCollection, PolylineCollection, Cartesian3, Cartesian2, Color, Material } from "cesium";
// Procedural cumulus clouds
const clouds = scene.primitives.add(new CloudCollection());
clouds.add({
position: Cartesian3.fromDegrees(-75.59, 40.04, 1500),
scale: new Cartesian2(40, 12),
maximumSize: new Cartesian3(40, 12, 15),
slice: 0.36,
});
// Low-level polyline collection
const polylines = scene.primitives.add(new PolylineCollection());
polylines.add({
positions: Cartesian3.fromDegreesArray([-75, 40, -70, 42, -65, 38]),
width: 3.0,
material: Material.fromType("Color", { color: Color.AQUA }),
});import { Primitive, GeometryInstance, PolylineGeometry, PolylineColorAppearance,
ColorGeometryInstanceAttribute, Cartesian3, Color, ArcType } from "cesium";
scene.primitives.add(new Primitive({
geometryInstances: new GeometryInstance({
geometry: new PolylineGeometry({
positions: Cartesian3.fromDegreesArray([0, 0, 5, 0]),
width: 10.0,
vertexFormat: PolylineColorAppearance.VERTEX_FORMAT,
arcType: ArcType.GEODESIC, // GEODESIC, RHUMB, or NONE
}),
attributes: { color: ColorGeometryInstanceAttribute.fromColor(Color.WHITE) },
}),
appearance: new PolylineColorAppearance({ translucent: false }),
}));| Enum | Values | Used By |
|---|---|---|
ArcType | GEODESIC, RHUMB, NONE | PolylineGeometry, PolygonGeometry |
CornerType | ROUNDED, MITERED, BEVELED | CorridorGeometry, PolylineVolumeGeometry |
ClassificationType | TERRAIN, CESIUM_3D_TILE, BOTH | GroundPrimitive, ClassificationPrimitive |
PrimitiveType | POINTS, LINES, TRIANGLES, etc. | Low-level Geometry |
CloudType | CUMULUS | CloudCollection |
Programmatic checks (primitive count, camera position) can pass while the visual output completely misses the rendered geometry. A few rules of thumb that recur in visual evaluations:
-PI/4 (-0.785 rad, -45°) pitch from a range of ~3 * gridFootprint. Pitches shallower than ~-0.6 rad can park the grid behind the camera or out of frame; pitches near -PI/2 flatten vertical extent and make the batch look like dots.-50°) and far ranges, the polygon shrinks to a thin strip at the bottom edge. Reduce range or use a flatter pitch so the polygon occupies the centre of the frame.When in doubt, viewer.flyTo(primitive) or viewer.camera.flyToBoundingSphere(primitive._boundingSpheres[0]) after primitive.ready will frame the batch automatically.
PerInstanceColorAppearance when each instance only needs a distinct color.flat: true on PerInstanceColorAppearance when lighting is unneeded; uses FLAT_VERTEX_FORMAT.allowPicking: false on Primitives that will never be picked to save GPU memory.asynchronous: true (default). Check primitive.ready before accessing instance attributes.BlendOption.OPAQUE on BillboardCollection/PointPrimitiveCollection when all items are opaque (up to 2x gain).heightReference.vertexFormat exactly to the appearance to skip unused vertex attribute computation.EllipsoidSurfaceAppearance over MaterialAppearance for surface geometry -- fewer vertex attributes.MVTDataProvider for tiled vector data as runtime 3D Tiles.© CesiumGS, Apache-2.0. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file
Just SKILL.md in skills/cesiumjs-primitives of CesiumGS/cesiumjs-skills.
Open the folder on GitHubat commit 5f4792c
Cesiumjs Primitives next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.
| Skill | Stars | Used in | Tokens | Auto-check | Licence | Repo updated |
|---|---|---|---|---|---|---|
| Cesiumjs Primitives this skillCesiumGS/cesiumjs-skills | 189 | — | ~7k | Automated safety check: Pass | Apache-2.0 | |
| Agent Collective Intelligence Coordinatorruvnet/ruflo | 74k | 2 repos | ~1k | Automated safety check: Pass | MIT | |
| Collection Digestoutline/outline | 41k | — | ~498 | Automated safety check: Pass | Custom licence | |
| Postman Collection Generatorsickn33/agentic-awesome-skills | 47k | 1 repos | ~1.4k | Automated safety check: Pass | MIT | |
| Dossier Collectruvnet/ruflo | 74k | — | ~1.1k | Automated safety check: Notes | MIT | |
| Author UI Primitivesremix-run/remix | 33k | — | ~2.5k | Automated safety check: Pass | MIT |
ruvnet/ruflo
Agent skill for collective-intelligence-coordinator - invoke with $agent-collective-intelligence-coordinator
outline/outline
Summarize what changed in an Outline collection since a date; use when the user asks what is new, what was updated, or wants a digest of recent documents.
sickn33/agentic-awesome-skills
Generate complete, import-ready Postman Collection v2.1 JSON files from natural language API descriptions or cURL commands.
ruvnet/ruflo
Build a graph-structured dossier on a seed entity via parallel fan-out + recursive expansion across web, memory, knowledge-graph, codebase, ADR index, and git intel
remix-run/remix
Build idiomatic headless primitives in packages/ui for Remix.
mukul975/Anthropic-Cybersecurity-Skills
Systematically collects, categorizes, and distributes indicators of compromise (IOCs) during and after security incidents to enable detection, blocking, and threat intelligence sharing.
CesiumGS/cesiumjs-skills
CesiumJS 3D Tiles - Cesium3DTileset, compressed and CAD-style glTF content, MVTDataProvider, UrlTemplate3DTilesDataProvider, styling, metadata, feature picking, voxels, point clouds, I3S, Gaussian…
CesiumGS/cesiumjs-skills
CesiumJS core utilities and networking - Resource, Color, Event, Request, RequestScheduler, error handling, helper functions, feature detection.
CesiumGS/cesiumjs-skills
CesiumJS materials and post-processing — Material, Fabric JSON, MaterialAppearance, ImageBasedLighting, PostProcessStage, PostProcessStageLibrary, bloom, depth of field, ambient occlusion, FXAA…
CesiumGS/cesiumjs-skills
CesiumJS spatial math - Cartesian3, Cartographic, Matrix4, Quaternion, Transforms, Ellipsoid, BoundingSphere, projections, coordinate conversions.
CesiumGS/cesiumjs-skills
CesiumJS terrain, globe, and environment - TerrainProvider, Globe, sampleTerrain, atmosphere, sky, fog, lighting, shadows, panoramas.
CesiumGS/cesiumjs-skills
CesiumJS viewer setup - Viewer, CesiumWidget, widgets, Ion token, Scene configuration, SceneMode, factory helpers, geocoders, platform services.
CesiumJS primitives and geometry - Primitive, GeometryInstance, Appearance, BufferPrimitive collections, GeoJsonPrimitive, Billboard/Label/PointPrimitive collections, built-in geometry shapes…. Cesiumjs Primitives is an agent skill from CesiumGS/cesiumjs-skills. CesiumJS primitives and geometry - Primitive, GeometryInstance, Appearance, BufferPrimitive collections, GeoJsonPrimitive, Billboard/Label/PointPrimitive collections, built-in geometry shapes, ground primitives, classification.
Cesiumjs Primitives fits situations like: rendering performance-critical static; vector geometry; loading GeoJSON without entities; creating custom shapes.
Run `npx skills add CesiumGS/cesiumjs-skills --skill cesiumjs-primitives -a claude-code`. Or copy the skill folder (skills/cesiumjs-primitives in CesiumGS/cesiumjs-skills) into .claude/skills/cesiumjs-primitives in your project. Claude Code loads it when a task matches its description.
Run `npx skills add CesiumGS/cesiumjs-skills --skill cesiumjs-primitives -a codex`. Or copy the skill folder (skills/cesiumjs-primitives in CesiumGS/cesiumjs-skills) into .agents/skills/cesiumjs-primitives in your project. Codex loads it when a task matches its description.
Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add CesiumGS/cesiumjs-skills --skill cesiumjs-primitives -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/cesiumjs-primitives, .gemini/skills/cesiumjs-primitives, .github/skills/cesiumjs-primitives and .opencode/skills/cesiumjs-primitives in your project.
SKILL.md names no scripts, command-line tools or credentials: Cesiumjs Primitives is instructions for the agent only.
SKILL.md contains no URLs. Any network use would come from the scripts or tools the agent runs. This is read from the text; nothing was executed.
Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. Review the folder before installing.
Cesiumjs Primitives is published under the Apache-2.0 licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.
About 7k tokens (SKILL.md is roughly 28k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full.
Skills that share tags, products or a category with Cesiumjs Primitives: Agent Collective Intelligence Coordinator (ruvnet/ruflo, 74k stars), Collection Digest (outline/outline, 41k stars), Postman Collection Generator (sickn33/agentic-awesome-skills, 47k stars) and Dossier Collect (ruvnet/ruflo, 74k stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.
CesiumGS (a GitHub organization) maintains it in CesiumGS/cesiumjs-skills, which has 189 GitHub stars. The repository holds 14 skills in this directory. The repository was last updated on September 14, 2026.
Source: CesiumGS/cesiumjs-skills on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.