RepoPilotOpen in app →

trunk-rs/trunk

Build, bundle & ship your Rust WASM application to the web.

Healthy

Healthy across the board

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 8w ago
  • 22+ active contributors
  • Distributed ownership (top contributor 35% of recent commits)
Show all 6 evidence items →
  • Apache-2.0 licensed
  • CI configured
  • Tests present

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/trunk-rs/trunk)](https://repopilot.app/r/trunk-rs/trunk)

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/trunk-rs/trunk on X, Slack, or LinkedIn.

Onboarding doc

Onboarding: trunk-rs/trunk

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/trunk-rs/trunk 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 the board

  • Last commit 8w ago
  • 22+ active contributors
  • Distributed ownership (top contributor 35% of recent commits)
  • Apache-2.0 licensed
  • CI configured
  • Tests present

<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 trunk-rs/trunk repo on your machine still matches what RepoPilot saw. If any fail, the artifact is stale — regenerate it at repopilot.app/r/trunk-rs/trunk.

What it runs against: a local clone of trunk-rs/trunk — 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 trunk-rs/trunk | 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 ≤ 86 days ago | Catches sudden abandonment since generation |

<details> <summary><b>Run all checks</b> — paste this script from inside your clone of <code>trunk-rs/trunk</code></summary>
#!/usr/bin/env bash
# RepoPilot artifact verification.
#
# WHAT IT RUNS AGAINST: a local clone of trunk-rs/trunk. If you don't
# have one yet, run these first:
#
#   git clone https://github.com/trunk-rs/trunk.git
#   cd trunk
#
# 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 trunk-rs/trunk and re-run."
  exit 2
fi

# 1. Repo identity
git remote get-url origin 2>/dev/null | grep -qE "trunk-rs/trunk(\\.git)?\\b" \\
  && ok "origin remote is trunk-rs/trunk" \\
  || miss "origin remote is not trunk-rs/trunk (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 "Cargo.toml" \\
  && ok "Cargo.toml" \\
  || miss "missing critical file: Cargo.toml"
test -f "src/main.rs" \\
  && ok "src/main.rs" \\
  || miss "missing critical file: src/main.rs"
test -f "Trunk.toml" \\
  && ok "Trunk.toml" \\
  || miss "missing critical file: Trunk.toml"
test -f "README.md" \\
  && ok "README.md" \\
  || miss "missing critical file: README.md"
test -f ".github/workflows/ci.yaml" \\
  && ok ".github/workflows/ci.yaml" \\
  || miss "missing critical file: .github/workflows/ci.yaml"

# 5. Repo recency
days_since_last=$(( ( $(date +%s) - $(git log -1 --format=%at 2>/dev/null || echo 0) ) / 86400 ))
if [ "$days_since_last" -le 86 ]; then
  ok "last commit was $days_since_last days ago (artifact saw ~56d)"
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/trunk-rs/trunk"
  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

Trunk is a WASM bundler and dev server specifically designed for Rust-to-WebAssembly projects. It orchestrates the full pipeline—compiling Rust to WASM via wasm-pack, bundling WASM binaries with JS/CSS/image assets via a source HTML file, serving with hot-reload, and shipping optimized output. Unlike generic bundlers, Trunk understands Rust build artifacts and the wasm-bindgen ecosystem natively. Single-package binary (src/ root) containing the CLI orchestrator, bundler pipeline, and dev server. The Cargo.toml pins specific versions (e.g., serde_yaml at =0.9.33 with a comment about deprecation), and examples/ contains 5+ standalone demo projects (cargo-manifest, cdylib, failing-rust, hooks, behind-reverse-proxy) that are integration tests. No monorepo; everything ships as one trunk binary.

👥Who it's for

Rust developers building web applications with WASM who want to skip manual webpack/vite configuration. They need rapid iteration (the built-in dev server with change detection and browser reload), asset bundling without boilerplate, and straightforward deployment—think Yew/Leptos/egui-wasm app developers.

🌱Maturity & risk

Production-ready and actively maintained. The repo shows version 0.22.0-beta.1 with CI/CD pipelines (.github/workflows/ci.yaml, release.yaml), Homebrew/crates.io distribution, Discord community support, and multiple examples in-tree. Rust MSRV is 1.90.0 suggesting recent maintenance. However, the 'beta' version tag indicates some APIs may still evolve.

Moderate risk: the dependency surface is large (~30+ major deps including axum, swc, reqwest, tokio) creating supply-chain exposure; beta versioning suggests breaking changes could occur between 0.x releases. Single primary maintainer visible in Cargo.toml (Anthony Dodd + Jens Reimann) means bus-factor risk. Conversely, GitHub Actions CI is robust and release.yaml suggests automated testing before crates.io publication.

Active areas of work

The repo is on 0.22.0-beta.1 track (version pinned in Cargo.toml). Active CI/CD setup (all workflows in .github/workflows/) including automated Homebrew releases (brew.yaml) and GitHub Pages docs (pages.yaml). The .versionrc and .convco/ templates indicate convential-commit-driven releases. The CONTRIBUTING.md and example projects suggest ongoing feature development rather than maintenance-only mode.

🚀Get running

git clone https://github.com/trunk-rs/trunk.git
cd trunk
cargo build --release
cargo install --path . trunk
trunk --version

Daily commands: No Makefile visible; use Cargo directly: cargo run -- serve (dev server at localhost:8080 watching for changes), or cargo run -- build (release build to dist/). For examples: cd examples/cargo-manifest && trunk serve.

🗺️Map of the codebase

  • Cargo.toml — Root manifest defining trunk's core dependencies (axum, tokio, wasm-bindgen) and project metadata; all contributors must understand the tech stack.
  • src/main.rs — Primary CLI entry point and command dispatcher; essential for understanding how trunk orchestrates build, serve, and watch operations.
  • Trunk.toml — Default configuration example showing trunk's own build configuration; demonstrates the config pattern that trunk enforces for user projects.
  • README.md — Project vision and user-facing API; clarifies what trunk does (WASM bundler) and its philosophy of optional-config patterns.
  • .github/workflows/ci.yaml — CI/CD pipeline defining test, build, and release processes; critical for understanding quality gates and release procedures.

🧩Components & responsibilities

  • CLI Entry (src/main.rs) (Clap (arg parsing), Tokio (async runtime)) — Parse arguments, dispatch to build/serve/watch/clean subcommands, coordinate overall workflow.
    • Failure mode: Panics on malformed arguments; exits with non-zero on compilation failure.
  • Build Pipeline (Cargo (compilation), wasm-bindgen (JS glue), file I/O) — Orchestrate Cargo invocation, run wasm-bindgen post-processing, collect and bundle assets.
    • Failure mode: Aborts if cargo fails, wasm-bindgen fails, or required assets missing; rolls back partial output.
  • Asset Processor

🛠️How to make changes

Add a new WASM project example

  1. Create a new example directory under examples/ (examples/my-framework/)
  2. Create a Cargo.toml with [package] name and lib/bin targets (examples/my-framework/Cargo.toml)
  3. Create index.html with <link rel="rust"/> for WASM entry point (examples/my-framework/index.html)
  4. Create src/main.rs or src/lib.rs with wasm_bindgen entry (examples/my-framework/src/main.rs)
  5. Optionally add Trunk.toml for custom hooks, asset processing, or profile overrides (examples/my-framework/Trunk.toml)
  6. Add a README.md explaining framework-specific setup (examples/my-framework/README.md)

Add CSS/SCSS preprocessing

  1. Create .scss or .css file in src/ directory (examples/cargo-manifest/src/index.scss)
  2. Reference the stylesheet in index.html using <link rel="stylesheet"/> (examples/cargo-manifest/index.html)
  3. Trunk auto-detects .scss and compiles via dart-sass; no config required (Trunk.toml)

Configure dev server proxy for backend API

  1. Create or edit Trunk.toml in project root (Trunk.toml)
  2. Add [[hooks.build]] or [[proxy]] section to route API requests to backend (examples/proxy/Trunk.toml)
  3. Reference docker-compose or backend service endpoint (examples/proxy/docker-compose.yaml)

🔧Why these technologies

  • Tokio + async-await — Enables non-blocking I/O for file watching, dev server, and asset processing; critical for responsive hot-reload during development.
  • Axum web framework — Lightweight, ergonomic HTTP server for dev server and HMR WebSocket support; minimal overhead for bundler-as-a-service.
  • wasm-bindgen — De facto Rust↔JS interop standard; generates glue code and type definitions for seamless WASM module integration.
  • Cargo as compilation driver — Leverages existing Rust build system rather than reimplementing; ensures compatibility with all Cargo features and workspaces.
  • dart-sass — Fast SCSS→CSS compilation with Dart backend; supports modern CSS features and integrates cleanly into asset pipeline.

⚖️Trade-offs already made

  • Optional config (Trunk.toml) with sensible defaults

    • Why: Minimize boilerplate for new users; most projects work out-of-the-box with just index.html + Cargo.toml.
    • Consequence: Some advanced use cases require explicit configuration; implicit behavior may surprise power users initially.
  • External tool invocation (cargo, dart-sass) vs. embedded libraries

    • Why: Avoid duplicate compilation logic; reuse battle-tested Rust and Dart ecosystems directly.
    • Consequence: Requires external binaries in PATH; slightly slower startup but better maintainability and correctness.
  • Synchronous HTML asset injection for WASM scripts

    • Why: Simple, predictable ordering; index.html patching is straightforward and debuggable.
    • Consequence: Less flexibility than dynamic module loading; all scripts loaded upfront rather than on-demand.

🚫Non-goals (don't propose these)

  • Not a framework or UI library; Trunk is purely a build tool and dev server.
  • Does not provide npm/node_modules management; JavaScript dependencies must be managed separately or via trunk's limited NPM integration.
  • Does not handle Rust server-side rendering or backend frameworks directly; focuses on WASM frontend bundling.
  • Not cross-platform in the sense of supporting Windows desktop apps or native binary distribution; WASM-specific (web target).
  • Does not provide authentication, database, or backend infrastructure; purely frontend tooling.

🪤Traps & gotchas

No apparent environment variables required in repo data (though examples/behind-reverse-proxy suggests proxy config is manual). Beta version: Cargo.toml shows 0.22.0-beta.1, so semver compatibility is not guaranteed between minor releases (breaking changes possible). serde_yaml deprecation: Cargo.toml pins serde_yaml at exactly 0.9.33 with a comment admitting it's deprecated; migrating off it is a known technical debt. Cross.toml exists: suggests cross-platform WASM binary builds are tested (e.g., Linux→ARM), but setup is non-obvious. Single Rust edition: edition = "2024" is mentioned but is not standard; verify this compiles with cargo check first.

🏗️Architecture

💡Concepts to learn

  • WASM module instantiation & JS binding — Trunk's core job is embedding wasm-bindgen-generated .wasm and .js glue into an HTML file; understanding how wasm modules load and call JS (and vice versa) is essential to debugging bundling issues.
  • Asset graph / dependency tree (HTML-centric) — Trunk parses the source index.html and recursively resolves <script>, <link>, <img> tags to build an asset dependency graph; this graph determines what gets bundled and optimized.
  • Hot module replacement (HMR) / browser reload — The dev server watches files, detects changes, rebuilds incrementally, and pushes updates to the browser via WebSocket; this is critical for Trunk's rapid iteration UX.
  • Asset fingerprinting (content-hash naming) — Trunk likely renames dist/ artifacts to include content hashes (e.g., app-abc123.wasm) for cache busting in production; visible in optimization deps like oxipng and minify-html.
  • Reverse proxy & WebSocket pass-through — examples/behind-reverse-proxy/ shows Trunk must work behind nginx; the dev server's WebSocket (for HMR) and asset serving must survive proxy rewriting.
  • Cargo manifest parsing & metadata extraction — Trunk reads Cargo.toml and Cargo.lock via cargo_metadata crate to determine WASM target, dependencies, and build flags; misalignment here breaks compilation.
  • File system event debouncing — notify-debouncer-full prevents rebuilds from firing multiple times when rapid file changes occur (e.g., editor auto-saves); critical for smooth dev experience.
  • rustwasm/wasm-pack — Trunk depends on wasm-pack under the hood for Rust→WASM compilation; essential sibling tool in the Rust WASM ecosystem.
  • yewstack/yew — Most common Rust web framework used with Trunk; typical use case is Yew frontend + Trunk bundler.
  • leptos-rs/leptos — Alternative Rust full-stack framework that also works with Trunk; competing but complementary ecosystem.
  • rustwasm/wasm-bindgen — Underlies wasm-pack's JS interop; Trunk packages and optimizes wasm-bindgen-generated JS glue.
  • parcel-bundler/parcel — Spiritual predecessor in generic web bundling space; Trunk is similar philosophy (zero-config bundling) but Rust-specific.

🪄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 integration tests for Trunk.toml configuration parsing and hook execution

The repo has multiple examples demonstrating Trunk.toml usage (hooks, cdylib, cargo-manifest examples) but no dedicated test suite validating configuration parsing, schema validation, and build hook execution. This is critical since Trunk.toml is central to the build system. Tests should cover the schemars-derived schema validation, YAML parsing edge cases, and hook lifecycle.

  • [ ] Create tests/integration/trunk_toml_parsing.rs covering valid/invalid Trunk.toml configurations
  • [ ] Add tests for build hook execution order and error handling (reference examples/hooks/Trunk.toml)
  • [ ] Validate schemars schema generation matches actual parsing behavior
  • [ ] Test YAML schema validation against the serde_yaml 0.9.33 pinned version

Add GitHub Actions workflow for testing cross-platform binary builds (Linux ARM64, macOS Silicon, Windows)

The repo has Cross.toml configuration for cross-compilation but no dedicated CI workflow validating builds for non-x86_64 targets. Given that Trunk is a build tool distributed via Homebrew and released as binaries, verifying ARM64 and other target builds is critical. The existing CI.yaml and release.yaml don't show explicit cross-platform testing.

  • [ ] Create .github/workflows/cross-build.yaml using cross-rs for ARM64 Linux targets
  • [ ] Add native macOS ARM64 (aarch64-apple-darwin) build validation in CI pipeline
  • [ ] Reference Cross.toml configuration and validate it matches CI target matrix
  • [ ] Test that release artifacts can be generated for all targets in Cross.toml

Add comprehensive documentation for Trunk.toml schema with examples for each configuration section

The repo has .convco template customization docs and multiple Trunk.toml examples scattered across examples/ directory, but no centralized schema reference documentation. The schemars dependency suggests schema documentation generation is possible. Contributors struggle to understand advanced features like hooks, asset pipelines, and custom resource configuration.

  • [ ] Generate JSON schema from schemars in src/ (identify config structs using schemars::JsonSchema)
  • [ ] Create docs/configuration.md documenting each Trunk.toml top-level field with schema annotations
  • [ ] Add subsections for [build], [hooks], [watch] with examples referencing specific examples/ directories
  • [ ] Include validation rules and error messages for common misconfigurations (reference examples/failing-rust/)

🌿Good first issues

  • The examples/failing-rust project appears to be a deliberate test case (its name suggests it tests error handling). Write integration tests that verify Trunk correctly reports Rust compilation errors and fails gracefully rather than corrupting dist/ output.
  • The .convco/ templates for commit messages (commit.hbs, header.hbs, footer.hbs, template.hbs) are present but no docs explain convco's purpose to contributors. Add a section to CONTRIBUTING.md explaining the conventional commit format that the CI expects.
  • oxipng and minify-html appear in deps (asset optimization), but the examples/ don't show before/after file size comparisons or documentation of when/how optimization is applied. Create a benchmarking example and docs showing optimization impact on cargo-manifest example assets.

Top contributors

Click to expand

📝Recent commits

Click to expand
  • 1705946 — feat: honor data-target-path for initializers and standardize hashing (asgardkat)
  • 19a8690 — feat: Retry to download tools on failure (deadbaed)
  • 189311d — ci(release): fix aarch64-pc-windows-msvc build: use llvm-strip (alisterd51)
  • 3da25c2 — build: switch to beta version (ctron)
  • 5e5fd1b — ci(release): add windows aarch64 target (alisterd51)
  • bca50ed — chore(ci): bump GitHub Actions and runner versions (alisterd51)
  • 00cc418 — chore: update generated schema (alisterd51)
  • dd1190a — chore: upgrade dependencies and remove obsolete dependencies (alisterd51)
  • 1e8a301 — fix: downlad node package in crate folder (MarcAntoine-Arnaud)
  • d57c604 — feat: update schema (MarcAntoine-Arnaud)

🔒Security observations

The Trunk codebase shows generally good security practices with modern dependencies and careful dependency selection. The primary concerns are the deprecated serde_yaml dependency and an incomplete view of the dependency list. The project uses reasonably secure defaults (LTO, panic=abort for release builds) and targets recent Rust versions. No obvious hardcoded secrets, SQL injection risks, or XSS vulnerabilities were identified in the provided file structure. Recommendations include: (1) Migrate away from deprecated serde_yaml, (2) Validate all dependencies via 'cargo audit', (3) Review necessity of all reqwest features, and (4) Establish security update procedures for the MSRV. The web-facing nature of this build tool means supply chain security is critical—consider implementing dependency pinning and vendoring in production builds.

  • Medium · Pinned serde_yaml version with deprecated status — Cargo.toml - serde_yaml dependency. The Cargo.toml pins serde_yaml to version 0.9.33 with a comment indicating it is deprecated. Using deprecated dependencies can lead to missed security updates and potential vulnerabilities. The comment suggests this was a temporary measure until a replacement is identified. Fix: Evaluate and migrate to an actively maintained YAML serialization library (e.g., serde-yaml successor or alternative). If serde_yaml 0.9.33 is required, establish a timeline for migration and monitor for security advisories.
  • Medium · Incomplete dependency list in Cargo.toml — Cargo.toml - dependencies section (truncated). The dependency list appears truncated at 'swc_' without completing the full SWC-related dependencies. This incomplete snippet makes it difficult to verify all transitive dependencies are secure and up-to-date. Fix: Provide complete Cargo.toml file and run 'cargo audit' to identify any known security vulnerabilities in dependencies. Ensure all SWC dependencies are explicitly specified and pinned to secure versions.
  • Medium · Use of reqwest with multiple features including hickory-dns — Cargo.toml - reqwest dependency. While reqwest is a reputable HTTP client, the combination of multiple features (stream, hickory-dns, json) increases the attack surface. DNS resolution via hickory-dns bypasses system DNS configurations which could be intentional but needs validation. Fix: Review if all reqwest features are necessary. Consider using only required features to minimize dependencies. Validate that custom DNS resolution (hickory-dns) is intentional and properly configured for your use case.
  • Low · Minimum Rust version may not receive security updates — Cargo.toml - rust-version field. The project targets Rust 1.90.0 as the minimum supported version. Older Rust versions may not receive critical security patches, affecting users building with older toolchains. Fix: Document the security support window for the minimum Rust version. Consider raising the MSRV periodically to ensure users are on versions receiving active security updates.
  • Low · Aggressive optimizations in release profile — Cargo.toml - [profile.release] section. The release profile uses LTO (Link Time Optimization) and panic=abort. While these are performance optimizations, they can make debugging security issues more difficult and reduce stack trace quality in production crashes. Fix: Consider maintaining separate debug symbols for release builds to aid in security incident investigation. Ensure panic handling doesn't mask critical errors in web server contexts.

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 · trunk-rs/trunk — RepoPilot