sceneview — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited sceneview (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
SceneView is a declarative 3D and AR SDK. One mental model across every platform:
SceneView { … } (3D) and ARSceneView { … } (AR) composables.Filament renderer. Artifacts: io.github.sceneview:sceneview:4.18.0 and io.github.sceneview:arsceneview:4.18.0.
SceneView { } and ARSceneView { } SwiftUIviews from the sceneview monorepo via Swift Package Manager (tag 4.18.0). RealityKit renderer.
[email protected] on npm (Filament.js + WebXR).sceneview_flutter plugin (PlatformView bridge).@sceneview-sdk/[email protected] (Fabric bridge).sceneview-mcp on npm — gives AI agents direct API access from chat.Nodes are declared as composables / SwiftUI views inside the parent SceneView's trailing content. No imperative scene.addChild(node).
Always treat `llms.txt` in the repo root as the source of truth. It carries the full SceneView / ARSceneView signatures, every node type, every helper. URL: <https://github.com/sceneview/sceneview/blob/main/llms.txt>
Repo-side samples/android-demo/src/main/java/io/github/sceneview/demo/demos/ contains a working demo for every node type — when in doubt, read the demo, do NOT improvise an API.
Trigger on any of:
.glb / .gltf / .usdz model in Compose."Skip for plain ARCore-SDK, Sceneform (deprecated), Unity, Unreal, or RealityKit projects that do NOT use the SceneViewSwift wrapper.
Verified against samples/android-demo/.../ModelViewerDemo.kt:
@Composable
fun ModelViewerDemo() {
val engine = rememberEngine()
val modelLoader = rememberModelLoader(engine)
val environmentLoader = rememberEnvironmentLoader(engine)
val modelInstance = rememberModelInstance(modelLoader, "models/helmet.glb")
SceneView(
modifier = Modifier.fillMaxSize(),
engine = engine,
modelLoader = modelLoader,
environmentLoader = environmentLoader,
) {
modelInstance?.let { instance ->
ModelNode(
modelInstance = instance,
scaleToUnits = 0.3f,
centerOrigin = Position(0f, 0f, 0f),
)
}
}
}AR tap-to-place is the same shape with ARSceneView. Verified against samples/android-demo/.../ARPlacementDemo.kt:
@Composable
fun ARPlacementDemo() {
val engine = rememberEngine()
val modelLoader = rememberModelLoader(engine)
val placedAnchors = remember { mutableStateListOf<Anchor>() }
var latestFrame by remember { mutableStateOf<Frame?>(null) }
ARSceneView(
modifier = Modifier.fillMaxSize(),
engine = engine,
modelLoader = modelLoader,
planeRenderer = true,
sessionConfiguration = { _, config ->
config.planeFindingMode = Config.PlaneFindingMode.HORIZONTAL_AND_VERTICAL
config.lightEstimationMode = Config.LightEstimationMode.ENVIRONMENTAL_HDR
},
onSessionUpdated = { _, frame -> latestFrame = frame },
onGestureListener = rememberOnGestureListener(
onSingleTapConfirmed = { event, node ->
if (node != null) return@rememberOnGestureListener
val frame = latestFrame ?: return@rememberOnGestureListener
val hit = frame.hitTest(event).firstOrNull {
it.trackable is Plane && (it.trackable as Plane).isPoseInPolygon(it.hitPose)
}
hit?.createAnchor()?.let { placedAnchors.add(it) }
}
),
) {
placedAnchors.forEach { anchor ->
key(anchor) {
AnchorNode(anchor = anchor) {
rememberModelInstance(modelLoader, "models/helmet.glb")?.let { instance ->
ModelNode(modelInstance = instance, scaleToUnits = 0.3f, isEditable = true)
}
}
}
}
}
}Note: ARSceneView takes a sessionConfiguration: (Session, Config) -> Unit lambda — there is NO rememberARSession() helper, do NOT invent one. AnchorNode takes a com.google.ar.core.Anchor instance; create one via hit.createAnchor() after a hit-test on the latest Frame.
null while loading. Always guard with ?.let { … } or ?:. Never !!.
remember* helpers handle this.For imperative code use modelLoader.loadModelInstanceAsync (see llms.txt § Threading rules).
extras. The canonical form for intensity/color/direction is top-level (verified against LightingDemo.kt):
LightNode(
type = LightManager.Type.POINT,
intensity = 30_000f,
direction = Direction(-x, -y, -z),
position = Position(x, y, z),
color = colorOf(r = 1.0f, g = 0.95f, b = 0.8f),
apply = { falloff(6f) }, // only Filament-builder extras go here
)type is com.google.android.filament.LightManager.Type (DIRECTIONAL, POINT, FOCUSED_SPOT, SPOT, SUN).
AnchorNode with a realcom.google.ar.core.Anchor from hit.createAnchor(). There are NO AnchorNode.image() / .face() / .plane() factory functions on Android in v4.2 — use AugmentedImageNode for tracked images and AugmentedFaceNode for face meshes (both in arsceneview package).
3D-only → io.github.sceneview:sceneview. AR → io.github.sceneview:arsceneview (it transitively includes sceneview).
rememberEngine / rememberModelLoader/ rememberMaterialLoader / rememberEnvironmentLoader belong at the top of the screen-level composable, NOT inside scroll lists or item composables.
Never call a decomposing or allocating getter inside `onFrame` (or any 30–60 Hz loop). Set the whole node.transform = … once instead of writing position / quaternion / scale one at a time (one-at-a-time writes recompose the matrix and drift — issue #2187); use Mat4.copyColumnsInto(scratch) not Mat4.toColumnsFloatArray() for per-frame uniform uploads; prefer the TRS-tuple slerp(startPosition, startQuaternion, startScale, …) when you already hold the components. Reading node.worldPosition / worldQuaternion per frame is fine now — those are cached. Always load via rememberModelInstance / rememberNode (cached + main-thread). Full table: docs/docs/performance.md § Hot Paths & Allocation-Free APIs (audit umbrella #2263).
This skill is most useful paired with the `android-cli` skill:
android run --apks=APK --activity=PKG/.MainActivity — install + launch inone call.
android screen capture --annotate -o ui.png + `android screen resolve--screenshot=ui.png --string="tap #N"` — visual UI testing of a 3D scene.
android layout --pretty -o ui.json — Compose UI tree dump (the 3D viewportreports as a single AndroidView, so for in-3D tap targets you still need pointerInput / hit testing).
android docs search "compose canvas" — underlying Compose APIs.io.github.sceneview.haptic.SceneViewHaptic wraps Android's Vibrator behind seven semantic presets plus low-level escape hatches. Get an instance with rememberHapticFeedback() inside a @Composable; it is a silent no-op (one Log.d, never throws) when the device has no vibrator or the consumer app omits the permission.
import io.github.sceneview.haptic.rememberHapticFeedback
@Composable
fun PlaceAnchorButton(onPlace: () -> Unit) {
val haptic = rememberHapticFeedback()
Button(onClick = { haptic.medium(); onPlace() }) { Text("Place") }
}light() medium() heavy() success() warning() error()selection(). Escape hatches: continuous(intensity, durationMs) and pattern(events). cancel() stops an in-progress vibration — rememberHapticFeedback() calls it automatically on dispose.
<uses-permission android:name="android.permission.VIBRATE" /> to its manifest — the sceneview library does not auto-merge it.
SceneViewSwift.SceneViewHaptic) and Web(sceneview.haptic.*). See llms.txt § Haptic Feedback.
helper, with their actual signatures pulled from llms.txt.
samples/android-demo/ for each of the 13 canonical patterns. Read the demo file, copy from it. Do not improvise.
docs/docs/migration.md for the full rename map.
When the user asks for a SceneView feature:
SceneView { } for 3D-only,ARSceneView { } for AR. Mention the matching Gradle artifact.
samples/android-demo/.../demos/ beforewriting code. If you can't find one, fall back to llms.txt. Never invent an API.
raw constructors for Engine / ModelLoader.
?.let { … }.Manifest.permission.CAMERA and thecom.google.ar.core <meta-data> entry.
docs/docs/migration.md and the local references/migration.md.
~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.