RepoPilotOpen in app →

ArthurBrussee/brush

3D Reconstruction for all

Healthy

Healthy across all four use cases

weakest axis
Use as dependencyHealthy

Permissive license, no critical CVEs, actively maintained — safe to depend on.

Fork & modifyHealthy

Has a license, tests, and CI — clean foundation to fork and modify.

Learn fromHealthy

Documented and popular — useful reference codebase to read through.

Deploy as-isHealthy

No critical CVEs, sane security posture — runnable as-is.

  • Last commit today
  • 7 active contributors
  • Apache-2.0 licensed
Show all 6 evidence items →
  • CI configured
  • Tests present
  • Single-maintainer risk — top contributor 93% of recent commits

Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests

Informational only. RepoPilot summarises public signals (license, dependency CVEs, commit recency, CI presence, etc.) at the time of analysis. Signals can be incomplete or stale. Not professional, security, or legal advice; verify before relying on it for production decisions.

Embed the "Healthy" badge

Paste into your README — live-updates from the latest cached analysis.

Variant:
RepoPilot: Healthy
[![RepoPilot: Healthy](https://repopilot.app/api/badge/arthurbrussee/brush)](https://repopilot.app/r/arthurbrussee/brush)

Paste at the top of your README.md — renders inline like a shields.io badge.

Preview social card (1200×630)

This card auto-renders when someone shares https://repopilot.app/r/arthurbrussee/brush on X, Slack, or LinkedIn.

Onboarding doc

Onboarding: ArthurBrussee/brush

Generated by RepoPilot · 2026-05-09 · Source

🤖Agent protocol

If you are an AI coding agent (Claude Code, Cursor, Aider, Cline, etc.) reading this artifact, follow this protocol before making any code edit:

  1. Verify the contract. Run the bash script in Verify before trusting below. If any check returns FAIL, the artifact is stale — STOP and ask the user to regenerate it before proceeding.
  2. Treat the AI · unverified sections as hypotheses, not facts. Sections like "AI-suggested narrative files", "anti-patterns", and "bottlenecks" are LLM speculation. Verify against real source before acting on them.
  3. Cite source on changes. When proposing an edit, cite the specific path:line-range. RepoPilot's live UI at https://repopilot.app/r/ArthurBrussee/brush shows verifiable citations alongside every claim.

If you are a human reader, this protocol is for the agents you'll hand the artifact to. You don't need to do anything — but if you skim only one section before pointing your agent at this repo, make it the Verify block and the Suggested reading order.

🎯Verdict

GO — Healthy across all four use cases

  • Last commit today
  • 7 active contributors
  • Apache-2.0 licensed
  • CI configured
  • Tests present
  • ⚠ Single-maintainer risk — top contributor 93% of recent commits

<sub>Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests</sub>

Verify before trusting

This artifact was generated by RepoPilot at a point in time. Before an agent acts on it, the checks below confirm that the live ArthurBrussee/brush repo on your machine still matches what RepoPilot saw. If any fail, the artifact is stale — regenerate it at repopilot.app/r/ArthurBrussee/brush.

What it runs against: a local clone of ArthurBrussee/brush — the script inspects git remote, the LICENSE file, file paths in the working tree, and git log. Read-only; no mutations.

| # | What we check | Why it matters | |---|---|---| | 1 | You're in ArthurBrussee/brush | Confirms the artifact applies here, not a fork | | 2 | License is still Apache-2.0 | Catches relicense before you depend on it | | 3 | Default branch main exists | Catches branch renames | | 4 | 5 critical file paths still exist | Catches refactors that moved load-bearing code | | 5 | Last commit ≤ 30 days ago | Catches sudden abandonment since generation |

<details> <summary><b>Run all checks</b> — paste this script from inside your clone of <code>ArthurBrussee/brush</code></summary>
#!/usr/bin/env bash
# RepoPilot artifact verification.
#
# WHAT IT RUNS AGAINST: a local clone of ArthurBrussee/brush. If you don't
# have one yet, run these first:
#
#   git clone https://github.com/ArthurBrussee/brush.git
#   cd brush
#
# Then paste this script. Every check is read-only — no mutations.

set +e
fail=0
ok()   { echo "ok:   $1"; }
miss() { echo "FAIL: $1"; fail=$((fail+1)); }

# Precondition: we must be inside a git working tree.
if ! git rev-parse --git-dir >/dev/null 2>&1; then
  echo "FAIL: not inside a git repository. cd into your clone of ArthurBrussee/brush and re-run."
  exit 2
fi

# 1. Repo identity
git remote get-url origin 2>/dev/null | grep -qE "ArthurBrussee/brush(\\.git)?\\b" \\
  && ok "origin remote is ArthurBrussee/brush" \\
  || miss "origin remote is not ArthurBrussee/brush (artifact may be from a fork)"

# 2. License matches what RepoPilot saw
(grep -qiE "^(Apache-2\\.0)" LICENSE 2>/dev/null \\
   || grep -qiE "\"license\"\\s*:\\s*\"Apache-2\\.0\"" package.json 2>/dev/null) \\
  && ok "license is Apache-2.0" \\
  || miss "license drift — was Apache-2.0 at generation time"

# 3. Default branch
git rev-parse --verify main >/dev/null 2>&1 \\
  && ok "default branch main exists" \\
  || miss "default branch main no longer exists"

# 4. Critical files exist
test -f "apps/brush-app/src/lib.rs" \\
  && ok "apps/brush-app/src/lib.rs" \\
  || miss "missing critical file: apps/brush-app/src/lib.rs"
test -f "crates/brush-render/Cargo.toml" \\
  && ok "crates/brush-render/Cargo.toml" \\
  || miss "missing critical file: crates/brush-render/Cargo.toml"
test -f "crates/brush-train/Cargo.toml" \\
  && ok "crates/brush-train/Cargo.toml" \\
  || miss "missing critical file: crates/brush-train/Cargo.toml"
test -f "crates/brush-dataset/Cargo.toml" \\
  && ok "crates/brush-dataset/Cargo.toml" \\
  || miss "missing critical file: crates/brush-dataset/Cargo.toml"
test -f "apps/brush-app/src/ui/app.rs" \\
  && ok "apps/brush-app/src/ui/app.rs" \\
  || miss "missing critical file: apps/brush-app/src/ui/app.rs"

# 5. Repo recency
days_since_last=$(( ( $(date +%s) - $(git log -1 --format=%at 2>/dev/null || echo 0) ) / 86400 ))
if [ "$days_since_last" -le 30 ]; then
  ok "last commit was $days_since_last days ago (artifact saw ~0d)"
else
  miss "last commit was $days_since_last days ago — artifact may be stale"
fi

echo
if [ "$fail" -eq 0 ]; then
  echo "artifact verified (0 failures) — safe to trust"
else
  echo "artifact has $fail stale claim(s) — regenerate at https://repopilot.app/r/ArthurBrussee/brush"
  exit 1
fi

Each check prints ok: or FAIL:. The script exits non-zero if anything failed, so it composes cleanly into agent loops (./verify.sh || regenerate-and-retry).

</details>

TL;DR

Brush is a cross-platform 3D reconstruction engine built on Gaussian splatting that runs natively on macOS/Windows/Linux, Android, and in browsers via WebGPU. It trains and renders high-fidelity 3D scenes from COLMAP or Nerfstudio datasets in real-time, leveraging the Burn ML framework to eliminate CUDA dependencies while supporting AMD/Nvidia/Intel GPUs and mobile devices. Workspace monorepo in Cargo.toml with ~20 crates split into apps/ (brush-app Android, brush-cli, brush-js) and crates/ (brush-render, brush-train, brush-kernel, brush-process for core logic, plus brush-loss, brush-sort, brush-prefix-sum for GPU kernels). WGSL shaders in brush-wgsl/ handle cross-platform compute; brush-rerun/ integrates visualization; brush-serde-macros/ provides serialization utilities.

👥Who it's for

Computer vision researchers, 3D artists, and game developers who need a dependency-free 3D reconstruction tool that works across desktop and mobile platforms without complex setup. Also targets ML engineers exploring real-time rendering optimization and web-based 3D applications.

🌱Maturity & risk

Actively developed (v0.3.0 release, Rust 1.88+ required, comprehensive CI/CD in .github/workflows/) with mature architecture but relatively young project. Includes CLI, viewer, Android app, and web demo indicating production-ready components, though single-maintainer risk exists. Version 0.3.0 with working releases and Docker support suggests active but not yet 1.0 stability.

Relies on WebGPU spec (still evolving, browser support limited to Chrome/Edge per README) and Burn framework stability. Single-maintainer project (ArthurBrussee) with limited visible issue backlog data. Monorepo complexity across 20+ crates increases refactoring risk; WGSL shader code represents critical graphics path with potential portability issues across GPU vendors.

Active areas of work

Recent version 0.3.0 release with multi-platform support. GitHub Actions CI (ci.yml, release.yml) indicates active testing and deployment. Dependabot configured suggesting dependency maintenance. Rerun integration for live training visualization suggests active feature development. Spelling/link checks in CI indicate documentation focus.

🚀Get running

Install Rust 1.88+, clone the repo: git clone https://github.com/ArthurBrussee/brush && cd brush. Build the default CLI: cargo build --release. Run web demo instructions in README or try Android app via cd apps/brush-app && cargo build --release targeting Android. For quick testing: brush --help shows CLI overview.

Daily commands: CLI: cargo run --release --bin brush -- --help. Web demo: See README link to arthurbrussee.github.io/brush-demo (requires Chrome/Edge). Android: Import apps/brush-app into Android Studio or cargo build --release --target aarch64-linux-android. Docker: See apps/Dockerfile for containerized environment. Dev with live visualization: brush train --input data/ --with-viewer (requires rerun installed per README).

🗺️Map of the codebase

  • apps/brush-app/src/lib.rs — Main entry point for the Brush application; coordinates GPU rendering pipeline, training loop, and UI integration across all platforms
  • crates/brush-render/Cargo.toml — Core rendering engine dependency; handles WebGPU-based Gaussian splatting rasterization, critical for real-time display
  • crates/brush-train/Cargo.toml — Training pipeline using Burn ML framework; orchestrates loss computation, optimization, and gradient updates for reconstruction
  • crates/brush-dataset/Cargo.toml — Dataset loading and preprocessing; abstracts input image sequences and camera calibration from COLMAP or other sources
  • apps/brush-app/src/ui/app.rs — UI application state machine; bridges GPU operations, user input, and cross-platform rendering (web, Android, native)
  • Cargo.toml — Workspace manifest defining all 18 member crates and shared dependencies; essential for understanding module organization and build graph
  • crates/brush-render-bwd/Cargo.toml — Backward pass for rendering; computes gradients w.r.t. Gaussian parameters, essential for training loop closure

🛠️How to make changes

Add a New Loss Function

  1. Create a new loss module in crates/brush-loss/src/ (e.g., my_loss.rs) exporting a loss computation function that takes predicted and target images and returns a scalar Burn tensor (crates/brush-loss/src/my_loss.rs)
  2. Register the loss in the loss module's public API by adding a pub fn and re-export in crates/brush-loss/src/lib.rs (crates/brush-loss/src/lib.rs)
  3. Update the training loop in crates/brush-train/src/ to conditionally apply your loss alongside existing L1/LPIPS losses (crates/brush-train/Cargo.toml)
  4. Add a UI toggle in apps/brush-app/src/ui/settings_panel.rs to enable/disable and weight the new loss during training (apps/brush-app/src/ui/settings_panel.rs)

Add a New UI Panel

  1. Create a new module in apps/brush-app/src/ui/ (e.g., my_panel.rs) implementing a Struct with an update() method that returns egui widget changes (apps/brush-app/src/ui/my_panel.rs)
  2. Export the new panel in apps/brush-app/src/ui/mod.rs and add it to the public UI struct (apps/brush-app/src/ui/mod.rs)
  3. Integrate the panel into the main app layout in apps/brush-app/src/ui/app.rs by instantiating it and calling its update() in the per-frame loop (apps/brush-app/src/ui/app.rs)
  4. Optionally add serialization hooks in apps/brush-app/src/ui/mod.rs to persist panel state across app restarts (apps/brush-app/src/ui/panels.rs)

Add Support for a New Dataset Format

  1. Create a new reader module in crates/brush-dataset/src/ (e.g., my_format.rs) that implements the Dataset trait, returning images, camera poses, and intrinsics (crates/brush-dataset/src/my_format.rs)
  2. Register the new reader in the dataset loader enum in crates/brush-dataset/src/lib.rs with a DatasetType::MyFormat variant (crates/brush-dataset/src/lib.rs)
  3. Update the file picker in apps/brush-app/src/ui/datasets.rs to detect your format by file extension or directory signature and instantiate the correct reader (apps/brush-app/src/ui/datasets.rs)
  4. Optionally add a test dataset in the repo and update CI to validate your format in .github/workflows/ci.yml (.github/workflows/ci.yml)

Add a New GPU Kernel Operation

  1. Create a new kernel module in crates/brush-kernel/src/ (e.g., my_op.rs) that wraps a Burn compute operation or custom WGSL shader (crates/brush-kernel/src/my_op.rs)
  2. Export the kernel from crates/brush-kernel/src/lib.rs and add it to the kernel dispatch logic (crates/brush-kernel/src/lib.rs)
  3. Integrate the kernel call into the rendering or training pipeline in crates/brush-render/src/ or crates/brush-train/src/ as appropriate (crates/brush-render/Cargo.toml)
  4. Add benchmarks in crates/brush-bench-test/ to validate performance and correctness against CPU reference implementations (crates/brush-bench-test/Cargo.toml)

🪤Traps & gotchas

WebGPU browser support is Chrome/Edge only (Firefox/Safari 'hopefully supported soon' per README). Rerun visualization requires separate installation (./brush_blueprint.rbl must exist). Android builds require Rust targets: rustup target add aarch64-linux-android. Training datasets expect COLMAP data or specific Nerfstudio format (unclear where schema docs live). No visible feature flags for disabling heavy dependencies (image formats, Rerun), so binary size may be large on embedded devices.

🏗️Architecture

💡Concepts to learn

  • Gaussian Splatting — Core 3D reconstruction technique that Brush implements — represents scenes as learned 3D Gaussians with efficient rasterization, directly impacts training speed and render quality
  • WebGPU — Cross-platform GPU API enabling Brush to run on desktop, mobile, and browsers without vendor-specific drivers; Brush uses WGSL shaders targeting this abstraction
  • wasm-bindgen — Rust-to-JavaScript FFI mechanism in brush-js/src/ enabling Rust engine to run in browsers; critical for web demo deployment
  • Differentiable Rendering — Brush implements backward passes (brush-render-bwd) to enable gradient-based Gaussian optimization from image reconstruction loss; core to training pipeline
  • Burn Framework's Autodiff — Underlying automatic differentiation system in brush-train that computes gradients for Gaussian parameters; enables training without manual backprop code
  • Prefix Sum (Scan) Algorithms — brush-prefix-sum crate implements GPU prefix scans needed for efficient Gaussian sorting and rendering depth ordering, critical performance optimization
  • Virtual Filesystem (VFS) — brush-vfs abstracts dataset loading across local files, URLs, and compressed streams, enabling dataset streaming and web integration
  • graphdeco-inria/gaussian-splatting — Original Gaussian splatting research and CUDA implementation that Brush reimplements in cross-platform Rust/WebGPU
  • nerfstudio-project/nerfstudio — NeRF training framework that Brush supports as input dataset format and uses as architectural inspiration for modular training pipeline
  • tracel-ai/burn — Rust ML framework underlying Brush's GPU compute and training loop — core dependency for differentiable Gaussian optimization
  • gfx-rs/wgpu — WebGPU implementation providing the cross-platform GPU abstraction layer that enables Brush to run on desktop, mobile, and browsers
  • rerun-io/rerun — Visualization companion tool integrated into Brush for live training monitoring and debugging (referenced in README and brush-rerun crate)

🪄PR ideas

To work on one of these in Claude Code or Cursor, paste: Implement the "<title>" PR idea from CLAUDE.md, working through the checklist as the task list.

Add WebGPU compatibility tests for multi-platform rendering backends

The repo targets macOS/Windows/Linux with AMD/Nvidia/Intel cards plus Android and browser support via WebGPU. However, there's no visible test suite validating that rendering works consistently across these backends. The crates/brush-render, crates/brush-render-bwd, and crates/brush-wgsl modules would benefit from integration tests that validate WGSL shader compilation and rendering correctness across different GPU vendors and platforms. This is critical for a reconstruction engine shipping on diverse hardware.

  • [ ] Create crates/brush-render/tests/webgpu_backends.rs to test shader compilation on simulated/actual WebGPU targets
  • [ ] Add integration tests in crates/brush-wgsl/tests/ validating WGSL code generation for different GPU architectures
  • [ ] Create a GitHub Actions workflow (.github/workflows/gpu_compat.yml) that runs tests on macOS (Metal), Linux (Vulkan), and Windows (DX12/Vulkan) runners
  • [ ] Document test results in README.md under a 'Platform Support' section with specific GPU/OS combinations validated

Add serialization round-trip tests for brush-serde and brush-serde-macros

The workspace includes crates/brush-serde and crates/brush-serde-macros for custom serialization, but the file structure shows no test directory for these critical serialization paths. Given that the system handles 3D Gaussian splat data (geometrically sensitive), serialization correctness is essential. A new test suite should validate that complex nested structures (especially from crates/brush-dataset and crates/colmap-reader) round-trip correctly through JSON/binary formats without precision loss.

  • [ ] Create crates/brush-serde/tests/round_trip.rs with tests for serde macro-generated code on sample Gaussian data structures
  • [ ] Add tests in crates/brush-serde-macros/tests/ validating macro expansion produces correct Serialize/Deserialize impls for derive attributes
  • [ ] Create fixtures in crates/brush-dataset/tests/fixtures/ with sample .json and .bin serialized splat data
  • [ ] Add a test validating float precision preservation (especially for 3D coordinates) in crates/brush-serde/tests/precision.rs

Add COLMAP dataset integration tests with benchmark suite

The crates/colmap-reader crate is critical for loading real-world camera and 3D data, but there's no visible test suite validating it correctly parses COLMAP output. Combined with crates/brush-bench-test, adding integration tests with real COLMAP datasets would validate the full pipeline from camera pose/sparse reconstruction to training. This directly improves the 'works on a wide range of systems' claim by ensuring data loading is robust.

  • [ ] Create crates/colmap-reader/tests/parsing.rs with unit tests for cameras.txt, images.txt, and points3D.txt parsing
  • [ ] Add crates/brush-bench-test/benches/colmap_load.rs benchmark measuring dataset loading performance across different COLMAP export sizes
  • [ ] Create test fixtures in crates/colmap-reader/test-data/ with sample COLMAP output from real reconstructions (small datasets from public sources)
  • [ ] Add integration test in crates/brush-process/tests/dataset_pipeline.rs validating end-to-end: COLMAP parse → training setup → splat output

🌿Good first issues

  • Add comprehensive integration tests in crates/brush-train/tests/ covering training convergence on synthetic datasets (currently no visible test/ directories despite 20+ crates)
  • Extend crates/brush-dataset/src/ to support NeRF datasets from other sources (e.g., Scannet format) by adding new loader modules alongside existing COLMAP reader
  • Document the WGSL shader compilation pipeline in crates/brush-wgsl/ — add rustdoc examples showing how shaders compile to different backends (SPIR-V for Vulkan, Metal, etc)

Top contributors

Click to expand

📝Recent commits

Click to expand
  • d0eaca6 — Pack GT to u32 RGBA, fold bg-composite + mask into loss kernel (#410) (ArthurBrussee)
  • eafcfc6 — Recompute SSIM partials in bwd, drop saved-for-backward tensors (#409) (ArthurBrussee)
  • dbef237 — Bump rerun from 0.31.3 to 0.31.4 (#408) (dependabot[bot])
  • 48ca31c — brush-js library + Vite-based web demos (#402) (ArthurBrussee)
  • 7640a81 — Per-splat backward + fused L1+SSIM loss (#401) (ArthurBrussee)
  • 266deb2 — Reference-pose framing bars (#399) (ArthurBrussee)
  • bf3dd6a — Gate force-split by growth_stop_iter (#398) (ArthurBrussee)
  • a6a1468 — Improve testing (#397) (ArthurBrussee)
  • e700993 — Update deps & fix WASM (ArthurBrussee)
  • 2602df6 — Fix flaky test, cleanups (ArthurBrussee)

🔒Security observations

The Brush 3D reconstruction engine shows a generally mature security posture with proper use of secure dependencies and build tools. However, there are notable concerns: (1) the Cargo.toml uses an unstable Rust edition (2024) which should be corrected to a stable version, (2) the rand dependency version appears incorrect and should be verified, and (3) web deployment via WebAssembly requires careful input validation and XSS protection. The project lacks visible security policy documentation. No hardcoded secrets, SQL injection risks, or Docker misconfigurations were detected. Recommendations focus on stabilizing the build configuration, establishing security policy, and ensuring web input handling is robust given the browser deployment capability.

  • Medium · Edition 2024 in Cargo.toml - Unstable Rust Edition — Cargo.toml - workspace.package.edition. The workspace.package edition is set to '2024', which is not a stable Rust edition. Stable editions are 2015, 2018, and 2021. Using an unstable or non-existent edition may cause compatibility issues, unexpected behavior, and potential security implications if the Rust compiler interprets this differently than intended. Fix: Change edition to a stable version (2021 recommended). Verify the actual intended edition and update to 'edition = "2021"'.
  • Medium · Outdated Rand Dependency — Cargo.toml - workspace.dependencies.rand. The crate uses 'rand = "0.10.0"', which appears to be a pre-release or non-standard version. The stable rand crate is at version 0.8.x with security patches. Using non-standard versions may introduce vulnerabilities or lack critical security updates. Fix: Update to a stable, well-maintained version of rand. Verify the correct version number and update to 'rand = "0.8"' or latest stable 0.8.x version.
  • Medium · Potential Unsafe Web Functionality — apps/brush-app/assets/sw.js and web infrastructure. The project includes wasm-bindgen and web infrastructure (service worker, manifest.json) suggesting WebAssembly/browser deployment. The presence of 'apps/brush-app/assets/sw.js' (service worker) combined with web deployment capabilities requires careful validation of all web-facing inputs to prevent XSS attacks. Fix: Review all web input handling, ensure Content Security Policy headers are properly configured, validate and sanitize all user inputs before rendering, and implement proper CORS policies.
  • Low · Default Members Configuration — Cargo.toml - default-members. The workspace has 'apps/brush-app' set as the default member. While not a direct security issue, this means cargo commands default to building a complex application with multiple dependencies. Ensure CI/CD pipelines explicitly specify which member to build to prevent accidental builds. Fix: Review CI/CD workflows to explicitly specify build targets. Verify '.github/workflows/ci.yml' and '.github/workflows/release.yml' explicitly name the intended build members.
  • Low · No Security Policy Visible — Repository root. The repository does not appear to have a SECURITY.md or security policy file visible in the provided file structure. This makes it unclear how to report security vulnerabilities responsibly. Fix: Create a SECURITY.md file documenting responsible disclosure procedures and security contact information.
  • Low · Broad Dependency Features Enabled — Cargo.toml - workspace.dependencies.image. The 'image' dependency enables multiple format handlers (png, webp, jpeg, exr). While necessary for functionality, each format parser increases attack surface. Ensure input validation on image files. Fix: Validate image file headers and sizes before processing. Consider limiting supported formats if not all are necessary. Monitor image format parser security advisories.
  • Low · External HTTP Request Capability — Cargo.toml - workspace.dependencies.reqwest. The project includes 'reqwest' with default-features disabled and 'stream' feature. This enables making external HTTP requests. Review code for proper TLS validation and error handling. Fix: Audit all reqwest usage for proper certificate validation, timeout configuration, and secure handling of external responses. Implement request size limits.

LLM-derived; treat as a starting point, not a security audit.


Generated by RepoPilot. Verdict based on maintenance signals — see the live page for receipts. Re-run on a new commit to refresh.

Healthy signals · ArthurBrussee/brush — RepoPilot