CLAUDE.md Kotlin Swift Backend

sceneview — CLAUDE.md

3D & AR SDK for Android (Jetpack Compose + Filament), iOS (SwiftUI + RealityKit), and Web. AI-first: llms.txt, MCP server, Copilot/Cursor rules. The only Compose-native 3D library.

CLAUDE.md · 208 lines
# SceneView — Claude Code guide

## Project purpose

SceneView is an **AI-first SDK**: its primary goal is to enable Claude (and other AI
assistants) to help developers build 3D and AR apps in Jetpack Compose. Every design
decision — API surface, documentation, samples, `llms.txt` — should be optimized so
that when a developer asks an AI "build me an AR app", the AI can produce correct,
complete, working code on the first try.

**Implication for contributors:** when adding or changing APIs, always ask "can an AI
read the docs and generate correct code for this?" If not, simplify the API or improve
the documentation until it can.

## QUALITY RULES (MANDATORY — every session, every commit)

**ZERO TOLERANCE for bugs reaching the user.** Every change must be verified before push.

### Before EVERY push to main:
1. **Compile check**: `./gradlew :sceneview:compileReleaseKotlin :arsceneview:compileReleaseKotlin`
2. **Unit tests**: `./gradlew :sceneview:test :arsceneview:testDebugUnitTest`
3. **Bundle build** (if store-affecting): `./gradlew :samples:android-demo:bundleRelease`
4. **Website JS** (if website changed): `node -c website-static/js/sceneview.js`
5. **Full gate**: `bash .claude/scripts/pre-push-check.sh`

### Rules:
- NEVER push code that doesn't compile
- NEVER push without running tests
- NEVER modify website JS without validating syntax
- NEVER deploy to stores without verifying the bundle builds locally first
- When an agent modifies code, ALWAYS verify compilation before committing
- If a review finds blockers, fix them ALL before pushing — no exceptions

### Quality plan: `.claude/plans/v4.0-quality-plan.md`

## About

SceneView provides 3D and AR as declarative UI for Android (Jetpack Compose, Filament,
ARCore) and Apple platforms (SwiftUI, RealityKit, ARKit) — iOS, macOS, and visionOS —
with shared logic in Kotlin Multiplatform.

## Full API reference

See [`llms.txt`](./llms.txt) at the repo root for the complete, machine-readable API reference:
composable signatures, node types, resource loading, threading rules, and common patterns.

## Design System (Google Stitch)

See [`DESIGN.md`](./DESIGN.md) for the complete design system: colors, typography, spacing,
radius, shadows, motion, breakpoints, and component patterns.

**Rules:**
- Always read `DESIGN.md` before generating any UI code (website, app, docs)
- Use CSS custom properties — never hardcode color/spacing/radius values
- Support both light and dark modes
- Follow Material 3 Expressive patterns

**Google Stitch MCP:** when configured, enables direct UI generation from Stitch projects.
To set up: `npm install @google/stitch-sdk`, then add the Stitch MCP server in Claude Code settings.

## When writing any SceneView code

- Use `SceneView { }` for 3D-only scenes (`io.github.sceneview:sceneview:4.1.0`)
- Use `ARSceneView { }` for augmented reality (`io.github.sceneview:arsceneview:4.1.0`)
- Declare nodes as composables inside the trailing content block — not imperatively
- Load models with `rememberModelInstance(modelLoader, "models/file.glb")` — returns `null`
  while loading, always handle the null case
- `LightNode`'s `apply` is a **named parameter** (`apply = { intensity(…) }`), not a trailing lambda
- For AR record-replay debugging, use `rememberARRecorder()` to capture sessions and
  `ARSceneView(playbackDataset = file)` to replay them — see `llms.txt` "AR Recording & Playback"

## Critical threading rule

Filament JNI calls must run on the **main thread**. Never call `modelLoader.createModel*`
or `materialLoader.*` from a background coroutine directly.
`rememberModelInstance` handles this correctly — use it in composables.
For imperative code, use `modelLoader.loadModelInstanceAsync`.

## Samples

One unified showcase app per platform — all features integrated into tabs.

| Directory | Platform | Demonstrates |
|---|---|---|
| `samples/android-demo` | Android | Play Store app — 4-tab Material 3 (3D, AR, Samples, About), 37 demos (24 3D + 13 AR) |
| `samples/android-tv-demo` | Android TV | D-pad controls, model cycling, auto-rotation |
| `samples/web-demo` | Web | Browser 3D viewer, Filament.js (WASM), WebXR AR/VR |
| `samples/ios-demo` | iOS | App Store app — 3-tab SwiftUI (3D, AR, Samples) |
| `samples/desktop-demo` | Desktop | Wireframe placeholder (NOT SceneView) — Compose Canvas, no Filament |
| `samples/flutter-demo` | Flutter | PlatformView bridge demo (Android + iOS) |
| `samples/react-native-demo` | React Native | Fabric bridge demo (Android + iOS) |
| `samples/common` | Shared | Helpers and utilities for all Android samples |
| `samples/recipes` | Docs | Markdown code recipes (model-viewer, AR, physics, geometry, text) |

## Module structure

| Module | Purpose |
|---|---|
| `sceneview-core/` | KMP module — portable collision, math, geometry, animation, physics (commonMain/androidMain/iosMain/jsMain) |
| `sceneview/` | Android 3D library — `Scene`, `SceneScope`, all node types (Filament renderer) |
| `arsceneview/` | Android AR layer — `ARScene`, `ARSceneScope`, ARCore integration |
| `sceneview-web/` | Web 3D library — Kotlin/JS + Filament.js (same engine as Android, WebGL2/WASM) |
| `SceneViewSwift/` | Apple 3D+AR library — `SceneView`, `ARSceneView` (RealityKit renderer, iOS/macOS/visionOS) |
| `samples/` | All demo apps — one per platform (`android-demo`, `ios-demo`, `web-demo`, etc.) |
| `mcp/` | `sceneview-mcp` — MCP server + `packages/` (automotive, gaming, healthcare, interior) + `docs/` |
| `flutter/` | Flutter plugin — PlatformView bridge to SceneView (Android + iOS), with native rendering |
| `react-native/` | React Native module — Fabric/Turbo bridge to SceneView (Android + iOS), with native rendering |
| `assets/` | Shared 3D models (GLB + USDZ) and environments for demos and website |
| `tools/` | Build utilities — Filament material generation, asset download, try-demo script |
| `website-static/` | Static HTML/CSS/JS website (sceneview.github.io) |
| `docs/` | MkDocs documentation source (built by CI) |
| `branding/` | Logo SVGs, brand guide, store asset specs |
| `buildSrc/` | Gradle build logic + detekt config |
| `.github/` | CI workflows + community docs (CoC, Security, Support, Governance, Sponsors, Privacy) |

## Version Location Map

**Source of truth:** `gradle.properties` -> `VERSION_NAME=X.Y.Z`

Every file below MUST be updated when bumping the version. Use `/version-bump` or `bash .claude/scripts/sync-versions.sh --fix`.

| Category | File | Pattern |
|---|---|---|
| **Android** | `gradle.properties` (root) | `VERSION_NAME=X.Y.Z` |
| | `sceneview/gradle.properties` | `VERSION_NAME=X.Y.Z` |
| | `arsceneview/gradle.properties` | `VERSION_NAME=X.Y.Z` |
| | `sceneview-core/gradle.properties` | `VERSION_NAME=X.Y.Z` |
| **npm** | `mcp/package.json` | `"version": "X.Y.Z"` |
| | `mcp/src/index.ts` | version in server info |
| | `sceneview-web/package.json` | `"version": "X.Y.Z"` |
| | `react-native/react-native-sceneview/package.json` | `"version": "X.Y.Z"` |
| **Flutter** | `flutter/sceneview_flutter/pubspec.yaml` | `version: X.Y.Z` |
| | `flutter/.../android/build.gradle` | `version 'X.Y.Z'` |
| | `flutter/.../ios/sceneview_flutter.podspec` | `s.version = 'X.Y.Z'` |
| **Docs** | `llms.txt` | `io.github.sceneview:sceneview:X.Y.Z` |
| | `README.md` | install snippets |
| | `CLAUDE.md` | code examples section |
| | `docs/docs/index.md` | install snippets |
| | `docs/docs/quickstart.md` | dependency snippets |
| | `docs/docs/llms-full.txt` | artifact versions |
| | `docs/docs/cheatsheet.md` | install snippets |
| | `docs/docs/platforms.md` | install line |
| | `docs/docs/android-xr.md` | install snippets |
| | `docs/docs/migration.md` | "upgrade to" version |
| **Website** | `website-static/index.html` | softwareVersion, badge, code |
| | `sceneview.github.io/index.html` | deployed version (separate repo) |
| **Samples** | `samples/android-demo/build.gradle` | versionName default |
| | `sceneview/Module.md` | version ref |
| **Swift** | `SceneViewSwift/` uses git tag `vX.Y.Z` | not a file version |

**Automation:**
- `bash .claude/scripts/sync-versions.sh` — checks all 30+ locations
- `bash .claude/scripts/sync-versions.sh --fix` — auto-fixes mismatches
- Claude Code plugin marketplace lives in [`sceneview/claude-marketplace`](https://github.com/sceneview/claude-marketplace) — run `bash scripts/sync-plugin-versions.sh` from THAT repo
- `bash .claude/scripts/quality-gate.sh` — full pre-push quality gate
- `bash .claude/scripts/cross-platform-check.sh` — API parity across platforms
- `bash .claude/scripts/release-checklist.sh` — pre-release validation

---

## Session continuity

Every Claude Code session MUST read this section first to stay in sync.

**NOTE FOR OTHER SESSIONS:** Always run `/sync-check` at the start and end of every session.
Never say "everything is good" without verifying published packages.

### Current state (last updated: 2026-05-11, session elegant-wright-b9cd6f — audit-sweep + 5-agent review)

- 🚀 **40 commits / 22 issues fermées / 5 follow-ups filés** (#971–#975) in a single session.
  - **Security cluster shipped**: DOM XSS in web-demo (#957 Kotlin + post-review JS-path patch in `3f369736`), --es demo registry validation (#958), Auto Backup exclude-all rules covering both `dataExtractionRules` (API 31+) AND `fullBackupContent` (API 24..30, added post-review) (#959), CSP meta on all 27 HTML files (#960).
  - **Build / release polish**: Filament pinned 1.71→1.70.2 to match committed `.filamat`s (#961), JaCoCo wired with CI artefacts + step-summary (#964), root `Package.swift` so SPM consumers ride the monorepo (no more `sceneview-swift` mirror lag) (#920), `release.yml` gate tightened + publish-rn + validate-spm jobs added (#962), web-demo finally building to `/web-demo/` via `jsBrowserDistribution` (#926, fixed post-review — `Webpack`-only task missed HTML).
  - **MCP** : version drift sweep (#941, follow-up sweep on remaining string-template leftovers in `de692709`), 9 dead modules dropped from npm tarball (-57 kB packed / -235 kB unpacked, #938), validator catches the `Scene { } → SceneView { }` rename (#939), `autoDetectIssue` regex catches AR+black/dark natural phrasings without false-positive on 3D-only sentences (#940 + post-review tightening in `c7f0399f`).
  - **UX** : haptic on shutter / mode chips / qaMode long-press (#956), QA pill tap-to-disable (#951), `LifecycleAwareLaunchedEffect` helper + GeometryDemo/DebugOverlay migration (#936; AnimationDemo REVERTED post-review due to camera teleport on foreground — tracked in #974), `rememberMaterialInstance` helper with PBR-key safety pattern (#937 + #971 follow-up for the 10-demo migration sweep).
  - **Docs** : iOS deep-link surfaced in README (#918), RN package name corrected with explicit "3.6.1 stale, 4.x publish pending" disclaimer (#924), Flutter pub.dev avoidance with git ref (#923), KDoc for the three smallest fully-undocumented files (#965 partial), `sceneview-web` hand-written `.d.ts` shipped (#946).
  - **Scripts** : `capture-play-store-screenshots.sh` lifted from chat history into `.claude/scripts/` (#919, with #975 follow-up for `--status-bar-px` flag + reject-multi-device).
- 🛡️ **5-agent Opus independent review** ran in parallel after the initial wave and caught **3 BLOCKERS + 4 MAJORS + 8 MINORS** before any public announcement:
  - DOM XSS duplicate in the inline-JS path of `samples/web-demo/src/jsMain/resources/index.html` (Kotlin fix didn't reach it).
  - MCP `list_platforms` rendered literal `${LATEST_SCENEVIEW_RELEASE}` text — substring was in `"..."` not `` `...` ``.
  - `data_extraction_rules.xml` covered 1 storage domain instead of 5, and `fullBackupContent` was missing entirely so API 24..30 still leaked to Drive.
  - `docs.yml` web-demo deploy used `jsBrowserProductionWebpack` (HTML missing) instead of `jsBrowserDistribution`.
  - Plus 4 MAJORs (rememberMaterialInstance PBR-key churn, AnimationDemo teleport-on-foreground, RN docs 3.6.1 stale, MCP residual `4.0.0`/`1.70.1` leftovers). All shipped in `de692709`.
- ✅ **3002 tests passing** end-to-end (sceneview 306 + arsceneview 123 + samples 41 + MCP 2532). 8 pre-existing orphan `dist/*.test.js` suite-loads still fail (modules dropped by #938, stale compiled tests).
- ✅ `:samples:android-demo:assembleDebug` → 161 MB APK built. Deploy website + docs CI green on `f2af4615`.
- 📊 **JaCoCo baselines surfaced**: `sceneview` 7.46 % line coverage, `arsceneview` 10.24 %. Honest starting point; delta-coverage gate is #973's job.
- 50 → 39 open issues. Remaining critical: #966 audit umbrella, #932 Delaunator thread-safety, #933 MaterialLoader coroutine leak, #934 APK 84→30 MB, #928 SceneViewSwift 21 silent stubs, #929 SceneViewSwift 9 test fails, #917 iOS App Store screenshots stale.

### Followups for next session

1. **#971** — migrate the remaining 10 demos to `rememberMaterialInstance` (good-first-issue; PBR-key safety doc'd in the helper).
2. **#972** — wire test infra in `samples/common/` so `LifecycleAwareLaunchedEffect` + `rememberMaterialInstance` get regression pins. Prereq for #971.
3. **#973** — JaCoCo delta-coverage gate. Establish baseline file + fail PR if `delta < -0.5pp`.
4. **#974** — state-preserving lifecycle pattern for AnimationDemo. 3 design options sketched.
5. **#975** — capture-play-store-screenshots.sh hardening (multi-device reject, --status-bar-px, variance threshold).
6. Optional: continue #965 KDoc sweep — 7 more fully-undocumented files (`RenderableManager.kt`, `NodeAnimator.kt`, `Cube/Cone/Cylinder/Sphere/Capsule/Torus.kt`, `Texture/VideoTexture/TextureSampler/ImageTexture.kt`, `UbershaderInstance.kt`, `sceneview-core/logging/Log.kt`). Pre-req for the Detekt `UndocumentedPublic*` rule.

### Previous state (last updated: 2026-05-08, session bold-villani-42902e — plugin marketplace + brand-scope cleanup + portfolio scrub)

- 🚀 **Claude Code plugin marketplace LIVE** at [`sceneview/claude-marketplace`](https://github.com/sceneview/claude-marketplace), single plugin scoped strictly to SceneView:
  - **sceneview** v4.0.11 (Apache-2.0) — `sceneview-mcp` + 11 namespaced contributor commands + cross-platform reminder hooks
  - Install: `/plugin marketplace add sceneview/claude-marketplace` then `/plugin install sceneview@sceneview`
- ⛔ **Strict rule** recorded in memory `feedback_sceneview_org_strict`: the `sceneview` GitHub org hosts ONLY SceneView-SDK artefacts. Personal-portfolio MCPs live elsewhere.
- 🔒 **Big repo scrub** committed in this session:
  - Removed off-topic personal-portfolio code from public sceneview/sceneview repo: `hub-gateway/`, `hub-mcp/`, `mcp-gaming/`, `mcp-interior/`, plus the strategy / submission docs that listed every personal MCP
  - Scrubbed in-place mentions in `CLAUDE.md`, `ROADMAP.md`, `CHANGELOG.md`, `docs/docs/ai-context.md`, `.gitignore`
  - Untracked `.claude/handoff*.md`, `.claude/plans/`, `.claude/marketplace-submissions/`, `.claude/SESSION_*.md`, `.dart_tool/`, `qa_log.txt` — these were carrying employer-

... [truncated — full content at source]
Share on X

こちらもおすすめ

Backend カテゴリの他のルール

もっとルールを探す

CLAUDE.md、.cursorrules、AGENTS.md、Image Prompts の全 244 ルールをチェック。