TripoSplatMac is the native Apple Silicon reference and production runner for TripoSplat. It uses PyTorch MPS to run the complete sampler locally and provides canonical validation fixtures for TripoSplatWebGPU.
It is not a WebGPU application. It does not use a browser, Hugging Face Space, remote GPU, tunnel, localhost API, or startup token. The Finder-launched app owns a short-lived inference worker process and stops it when the app exits. Images, intermediate tensors, generated scenes, and logs remain on the Mac.
- Apple Silicon Mac (
arm64) with Apple Metal Performance Shaders (MPS) - macOS 14.0 or newer — macOS 26 or 27 is not required
- 16 GiB unified memory recommended. This is advisory rather than a hard compatibility gate because lower-memory Macs have not yet been broadly qualified; measured MPS allocation exceeded 4 GiB on the validation host.
- Enough storage for any missing models plus 1 GiB of working space is required. About 5.2 GiB covers a fresh app/model setup; 8 GiB free is recommended.
- Internet access for the first model download; verified cached models work offline
At launch, System Check… reports the detected processor, macOS version, MPS availability, bundled Python/PyTorch/NumPy versions, unified memory, model-cache state, and free storage. Hard failures disable generation; advisory memory or storage recommendations remain visible without blocking it. Copy diagnostics exports the complete report as JSON.
The packaged app does not support Intel Macs, AMD/Hackintosh systems, or Intel Macs with AMD graphics. It does not require Core AI, Core ML, or the Apple Neural Engine; inference runs through bundled PyTorch on Apple MPS.
A notarized public DMG is not currently claimed by this repository. Check
GitHub Releases for a
signed TripoSplatMac-<version>-arm64.dmg. If no installer is listed, run from
source using the development instructions below.
For a published installer:
- Download the signed DMG on an Apple Silicon Mac running macOS 14.0 or newer.
- Open the DMG and drag TripoSplatMac onto the Applications shortcut.
- Eject the DMG, then open TripoSplatMac from Applications.
The packaged app contains Python, PyTorch, Qt, and its native runtime libraries. The first generation requires an internet connection and about 3.52 GiB for revision-locked model weights; later runs work offline from the verified cache.
Maintainers can create a local release candidate with:
bash scripts/build_release.shWithout release credentials this produces an ad-hoc-signed DMG for local
validation only. It must not be presented as a Gatekeeper-ready public release.
For public distribution, provide a Developer ID Application identity and a
notarytool keychain profile:
export MACOS_CODESIGN_IDENTITY="Developer ID Application: YOUR TEAM (TEAMID)"
export MACOS_NOTARY_PROFILE="triposplat-notary"
bash scripts/build_release.shThe script signs bundled native code and the final DMG, submits it to Apple, staples the notarization ticket, and runs Gatekeeper and mounted-image checks. Credentials remain in the developer keychain and are never stored here.
- Source version:
TripoSplatMac 0.3.1 - Distribution status: Developer ID-signed GitHub prerelease; notarization is pending, so Gatekeeper may block the downloaded application
- Declared deployment target: Apple Silicon (
arm64) and macOS 14.0 or newer - Qualified host: Apple M3 Max running macOS 26.3; macOS 14 compatibility is a deployment target and has not yet been independently validated
- Official source:
VAST-AI-Research/TripoSplatata78fa12d06dbf1381ca548bfac32bb68cb8c451d - Model revision:
VAST-AI/TripoSplatatde3b99ab2627d565a8d5fc40f2db52557b82b974 - Sampler: 20 fp32 MPS Euler/CFG steps, 40 official DiT calls
- Canonical flow result: bit-exact, qualification pass, strict pass, maximum
latent and camera error
0.0 - Packaged trajectory result: 40 invocations and 200 canonical tensors checked, with zero hash mismatches
- Fixed-seed full-pipeline result: development and packaged runners produced byte-identical final latent, camera, prepared image, PLY, SPLAT, and preview
The checked-in reports are historical evidence from the qualified host, not CI
results for future commits. The exact flow boundary and one fixed-seed
end-to-end artifact baseline passed; broader hardware, minimum-OS, and
renderer-pixel qualification remain separate claims. See
docs/validation.md and
CONTRIBUTING.md.
TripoSplatMac follows semantic versioning (MAJOR.MINOR.PATCH). The current
source version is 0.3.1 with macOS bundle build 4. The fused-surface GLB
exporter was introduced in TripoSplatMac 0.3.0 and now has exporter schema
version 3.0. Exported files use the standard glTF/GLB 2.0 container;
exporter 3.0 identifies this app's reconstruction contract independently of
the glTF version. Generated metadata.json and GLB extras record these
versions.
Use triposplat-mac --version (or triposplat-mac-reference --version) to
query the installed application version.
- Open
TripoSplatMac.appfrom Finder. - Choose or drag in PNG, JPEG, WebP, AVIF, or TIFF input.
- On first generation, allow the app to download and checksum-verify the locked 3.52 GiB model package.
- Watch preprocessing, model, conditioning, all 20 sampler-step, and decode progress.
- Inspect the generated scene in the native Gaussian-splat viewer. Drag to orbit,
Shift-drag or middle-drag to pan, scroll to zoom, and use Reset view (or
press
R) to restore the fitted camera. - Export standards-compatible binary 3DGS
.ply, legacy 32-byte.splat, or a broadly compatible.glbreconstructed triangle surface, or reveal the run folder in Finder. The GLB fits a Poisson indicator to consistently oriented anisotropic surface splats, removes disconnected artifacts, fills enclosed holes, and stores SH-DC colors as broadly compatible opaque PBR material groups.
Generated runs are stored under ~/Documents/TripoSplatMac/. Models persist
under:
~/Library/Caches/TripoSplatMac/models/de3b99ab2627d565a8d5fc40f2db52557b82b974/
Logs are written to:
~/Library/Logs/TripoSplatMac/TripoSplatMac.log
The cache and output locations can be overridden during development with
TRIPOSPLAT_MAC_MODEL_DIR and TRIPOSPLAT_MAC_OUTPUT_DIR.
To inspect both capability states on any Mac, launch:
.venv/bin/triposplat-mac --debug-capabilitiesThis opens separate Debug: supported and Debug: unsupported windows with simulated reports. Both are UI-only previews: image selection and generation are disabled, so the mode is safe even when the host Mac is unsupported. The packaged executable accepts the same flag:
dist/TripoSplatMac.app/Contents/MacOS/TripoSplatMac --debug-capabilitiesPySide6 plus PyInstaller was selected over a SwiftUI/Python bundle or Tauri sidecar because it preserves the already-qualified Python/PyTorch runtime with the fewest translation and packaging risks:
PySide6 application
├─ image selection, progress, cancellation, preview, export
└─ managed multiprocessing worker
├─ locked model manager and persistent cache
├─ official native preprocessing and encoders
├─ exact fp32 MPS 20-step sampler
├─ official native octree/Gaussian decoder
└─ PLY, SPLAT, GLB triangle-mesh, preview, and metadata exports
The worker uses process queues and a cancellation event. It does not open a
port or accept commands from the network. The normal UI does not expose
developer fixture controls. The same app executable provides explicit
--validate-flow and --self-test modes for reference work.
The model is not bundled into the .app: model files total 3,779,190,284
bytes and are revision-locked by size and SHA-256. Interrupted downloads use a
.part file and resume when the server supports HTTP ranges. A verified
receipt avoids rehashing several GiB on every launch.
Requirements:
- Apple Silicon Mac
- macOS 14.0 or newer
- Python 3.12
- Xcode Command Line Tools
- At least 8 GiB free disk space for the development environment, app build, models, and temporary packaging files
cd /path/to/TripoSplatMac
bash scripts/setup_dev.shThe setup creates .venv, installs the exact validated runtime and packaging
tools, installs this project in editable mode, and runs the device/source
self-test.
Download and verify all models before running, or let the UI do this on its first generation:
.venv/bin/triposplat-mac --download-modelsFor development with an existing cache:
export TRIPOSPLAT_MAC_MODEL_DIR=/path/to/ckptsThe directory must contain the five paths declared in
triposplat_mac/model/manifest.py.
Files are never silently substituted.
.venv/bin/triposplat-macRun one image without opening the UI:
.venv/bin/triposplat-mac --run input.png --seed 42 --num-gaussians 262144The normal app fixes the sampler at the qualified 20 steps, guidance 3, and
shift 3. Seed and Gaussian count remain user controls.
Run the fast contributor gate before packaging:
.venv/bin/python -m pytest
.venv/bin/python -m triposplat_mac.cli --self-testThe project currently uses tests and runtime/package validation as its quality checks; no separate formatter, linter, or static type checker is configured. The self-test requires a supported Apple Silicon host with MPS.
Build the macOS application:
bash scripts/build_app.sh
open dist/TripoSplatMac.appThe build regenerates the application icon, runs the unit tests, creates
dist/TripoSplatMac.app, and validates the frozen runtime. PyInstaller produces
an Apple Silicon, windowed, onedir bundle containing Python, PyTorch,
torchvision, Qt, and required native libraries. Model checkpoints remain in the
user cache so application updates do not redownload them. If invoking
PyInstaller directly, run .venv/bin/python scripts/generate_icon.py first.
Validate an existing bundle's structure and managed runtime:
.venv/bin/python scripts/validate_package.py \
--app dist/TripoSplatMac.appThis is not a static-only inspection: it executes the frozen self-test and therefore requires a supported Apple Silicon/MPS host.
Run the complete packaged flow gate and write both the detailed flow report and the combined package summary:
.venv/bin/python scripts/validate_package.py \
--app dist/TripoSplatMac.app \
--full-flow \
--model-dir /path/to/ckpts \
--fixture-dir fixtures/flow20-fp32-trajectory \
--report docs/packaged-flow20-validation.json \
--summary-report docs/packaged-functional-test.json--report belongs to the packaged flow validator. --summary-report writes the
combined structure, self-test, and flow evidence. To compose a new package
summary from an existing flow result instead of rerunning the model, pass
--flow-report PATH with --summary-report PATH; --flow-report and
--full-flow are mutually exclusive.
The release reports checked into this project are:
docs/pre-extraction-flow20-validation.json: untouched hybrid baselinedocs/development-flow20-validation.json: extracted development runnerdocs/packaged-flow20-validation.json: final.apprunner, including all 40 calls and 200 trajectory tensorsdocs/packaged-functional-test.json: packaged self-test plus numerical gatedocs/package-structure-test.json: arm64/signature/resources/port checksdocs/ui-functional-test.json: drag/drop, paths with spaces, export/reveal, MPS and unsupported-Mac states, cancellation, worker shutdown, and interrupted-run relaunchdocs/finder-launch-test.json: LaunchServices start and clean application exitdocs/development-full-pipeline.json: development image-to-PLY/SPLAT run and artifact hashesdocs/packaged-full-pipeline.json: packaged image-to-PLY/SPLAT run and artifact hashesdocs/full-pipeline-reproducibility.json: byte-exact development-versus-package artifact comparisondocs/model-cache-validation.json: all five locked files verified for offline use with zero network requests
These JSON files are historical evidence. Platform values describe the host that produced a report, while temporary and relative paths only identify the run layout; compatibility claims come from the explicit compatibility fields.
Run the non-interactive UI lifecycle smoke:
QT_QPA_PLATFORM=offscreen .venv/bin/python scripts/validate_ui.py \
--report docs/ui-functional-test.jsonDirect in-process canonical validation:
.venv/bin/triposplat-mac \
--validate-flow \
--model-dir /path/to/ckpts \
--fixture-dir fixtures/flow20-fp32-trajectory \
--report docs/development-flow20-validation.json \
--output-dir /tmp/triposplat-reference-outputThis emits the final fp32 latent and camera, exact hashes, qualification and strict diagnostics, all 40 per-call trajectory comparisons, MPS allocation data, model-load timing, and sampler timing. The fixture remains suitable as the numerical oracle for TripoSplatWebGPU.
Capture every step input and all 40 conditional/unconditional DiT predictions:
.venv/bin/triposplat-mac \
--capture-trace \
--model-dir /path/to/ckpts \
--fixture-dir fixtures/flow20-fp32-trajectory \
--output-dir /tmp/triposplat-flow-traceTrace mode wraps the official sampler only for developer capture. Normal app inference and release validation continue to call the untouched official sampler directly.
The normal full-pipeline run writes a metadata.json beside every result with
the source/model revisions, precision boundary, seed, sampler configuration,
elapsed time, MPS memory, and artifact names.
result.ply: binary little-endian Gaussian PLYresult.splat: compact 32-byte-per-Gaussian splat streamresult.glb: a glTF 2.0 indexed triangle mesh with shared positions, recomputed outward normals, 32-bit indices, and opaque SH-DC-derived PBR material groups. The exporter selects disk-like anisotropic splats, propagates their normal orientation across tangent-connected neighbors, fits a bounded Poisson indicator, removes small islands, fills enclosed holes, and extracts a smoothed Lewiner marching-cubes surface. It retries at lower fixed resolutions if the surface exceeds the 500,000-triangle budget. This is a reconstructed surface rather than one primitive per Gaussian; PLY/SPLAT remain the appearance-faithful formats.final-latent.f32: final[1,8192,16]little-endian fp32 flow latentfinal-camera.f32: final[1,1,5]little-endian fp32 camera stateprepared.png: exact RGB image supplied to the encoderspreview.jpg: lightweight native orthographic result previewmetadata.json: reproducibility and benchmark metadata
The preview is an inspection aid, not a canonical rendered-pixel validator.
The local .app is structurally ready for Developer ID signing but uses only
an ad-hoc signature because no certificate or Apple notarization credentials
are stored in this project.
After building:
codesign --force --deep --options runtime \
--entitlements app/macos/entitlements.plist \
--sign "Developer ID Application: YOUR TEAM" \
dist/TripoSplatMac.app
ditto -c -k --keepParent dist/TripoSplatMac.app dist/TripoSplatMac.zip
xcrun notarytool submit dist/TripoSplatMac.zip \
--keychain-profile YOUR_NOTARY_PROFILE --wait
xcrun stapler staple dist/TripoSplatMac.app
spctl --assess --type execute --verbose dist/TripoSplatMac.appDo not use ad-hoc signing for public distribution.
- Numerical and operational qualification was recorded on an M3 Max host running macOS 26.3. That is historical test evidence, not a compatibility floor: the packaged application requires macOS 14.0 or newer. A 16 GiB Apple Silicon run has not been completed.
- Cancellation occurs between expensive DiT calls; the active call is allowed to finish to avoid corrupting MPS state.
- First-run model setup requires network access. After the verified cache is complete, inference works offline.
- The initial local build is ad-hoc signed and will require Developer ID signing, notarization, and distribution testing before release.
- The native viewer targets macOS OpenGL 4.1 and performs CPU depth sorting with GPU covariance projection and anisotropic Gaussian blending. Transparency is the standard sorted-splat approximation when Gaussian volumes intersect.
- Flow-boundary parity is established. Full-pipeline canonical artifact and
rendered-pixel qualification are maintained separately and must not be
conflated with the
0.0flow result. The recorded fixed-seed development and packaged full-pipeline artifacts are byte-identical. TripoSplatMac explicitly seeds the official decoder's device-global random stream so fixed-seed application runs are repeatable.
TripoSplatMac owns Python, PyTorch, MPS, model download/reference tooling, and canonical fixture generation. TripoSplatWebGPU remains a static JavaScript/TypeScript, ONNX, WASM, and WebGPU project. It must not import this application, start its worker, expose a token field, or require localhost.
See docs/extraction-inventory.md for the
source classification and migration map.