Install in seconds
Install this skill
Copy the command and run it in your terminal. You can review the source before installing.
terminal
git clone https://github.com/crbnos/carbon

Works with Git. The repository opens in your current directory.

πŸ¦€
AI EngineeringTypeScript

Rust

by crbnos

Rust coding conventions for Carbon's cargo workspace, emphasizing safe async/FFI patterns, ownership choices, error handling, and performance profiling when working with OpenCASCADE and FCL bridges.

2.3K stars318 forksAdded 2026/07/20
agentic-platformassemblylinebusinesserpleanmanagementmanufacturingmcp-servermespostgresqlqmsreact-routersupabasetypescript

Documentation

README

rust β€” how Carbon writes Rust (tokio + heavy C++ FFI)

The workspace: crates/{occt-bridge,collision,converter,planner} (cxx bridges to OpenCASCADE + FCL, geometry, motion planning) and apps/assembler (axum service). The defining constraint: CPU-bound, non-yielding C++ behind async HTTP β€” most rules below exist because of it. Several are measured facts from this repo, not folklore.

Async/tokio discipline β€” the rules that carry this service

  1. Sync C++/CPU work never runs on an async worker. Tokio's ~cores worker threads poll every socket; a non-awaiting FFI call pins one for its full duration. Measured here: running convert inline at c=64 took /health p99 from 7ms to 296ms β€” one full convert of starvation; real files block minutes. Default: tokio::task::spawn_blocking(move || ffi_work()).await. (block_in_place only when you must keep borrowing !Send locals; never on a current-thread runtime.)
  2. The blocking pool is the queue. Cap it near core count (Builder::new_multi_thread().max_blocking_threads(n)) and excess spawn_blocking tasks queue inside tokio β€” graceful backpressure with zero 429/queue code. apps/assembler/src/main.rs does exactly this; keep +2 headroom so tokio::fs ops don't starve behind long converts.
  3. Never hold a lock across .await. House pattern: do all locking inside sync/blocking scopes (apps/assembler/src/cache.rs β€” LRU behind std::sync::Mutex, lock held for map ops only, never crosses an await). Prefer std::sync::Mutex for short non-await sections (faster); tokio::sync::Mutex only when a guard genuinely must cross an await β€” restructure first.
  4. rayon stays off the tokio runtime. The planner's par_iter sweeps run inside spawn_blocking closures. Never .par_iter() in an async fn. Remember rayon's pool is process-global: per-request fan-out multiplied by concurrent requests oversubscribes β€” measured here, N single-threaded requests across N cores beat NΓ—all-core fan-outs under load (ASSEMBLER_MESH_PARALLEL=0 exists for the same reason on the C++ side).
  5. Timeout β‰  cancellation for blocking work. tokio::time::timeout stops the await, not the FFI already running on the blocking pool. Bound the work itself (early-stop callbacks β€” see the planner's FCL canStop() threshold nodes) or accept run-to-completion.
  6. Channels: oneshot to bridge a blocking/rayon result to a handler, mpsc::channel(n) for bounded many→one, watch for latest-value config, broadcast for shutdown fan-out. Bound all fan-out (buffer_unordered(limit), Semaphore) — never unbounded spawn loops.
  7. Shutdown: prefer awaiting completion (axum's .with_graceful_shutdown(...), JoinSet::join_next()) over cancel-then-sleep β€” a fixed sleep is fake-graceful.

Ownership & shared state β€” decision table

Need Use In-repo example
Share read-mostly across tasks Arc<T> AppState fields
Concurrent map, sharded locks DashMap plan job store, progress store
Byte-bounded LRU Mutex<LruCache> (ns-held, sync scopes only) cache.rs
One-time global init OnceLock / std::sync::Once shared reqwest::Client; C++ std::call_once for OCCT init
Counters / phase flags atomics (AtomicU64, AtomicU8, relaxed) progress.rs
Lazy memo inside a struct OnceCell/OnceLock field Component::vol_cache, sym_axis_cache
Zero-copy payload sharing bytes::Bytes (clone = refcount) cached GLB/graph uploads

Signatures take &str/&[T]; clone only for ownership transfer. _else variants (unwrap_or_else, ok_or_else) when the eager argument allocates.

FFI (cxx) β€” the sharp edges

  • Bridges live in crates/occt-bridge (OCCT) and crates/collision (FCL), via the cxx crate; C++ exceptions map to Result at the bridge.
  • C++ types are !Send/!Sync by default. Keep handles thread-confined inside one spawn_blocking closure; move plain data (Vec/f64) out. When a wrapper genuinely is shareable, unsafe impl Send/Sync with the justification in a comment β€” in-repo precedent: SharedBvh and CollisionWorld (immutable after construction, so concurrent reads are sound). No justification comment = review reject.
  • Global C++ state is real: OCCT config must be initialized once (std::call_once in occt.cc) β€” per-call mutation of process-global state was this repo's original concurrency bug.
  • // SAFETY: comment on every unsafe block, no exceptions.
  • Don't set panic = "abort" without checking the C++ exception/unwind story at the cxx boundary first.

Errors β€” the house convention (verified, not aspirational)

Carbon does not use thiserror/anyhow. Errors are hand-rolled structs mirroring the wire contract: ConvertError { code, message } (crates/converter), ApiError { status, code, message } (apps/assembler), with From impls at the boundary. Follow that for service-contract errors. thiserror is fine for a new library crate with no wire contract; never leak anyhow from a library. ? over match chains; no unwrap/expect outside tests and provably-infallible spots.

Performance β€” measured habits

  • Measure, don't guess; always --release. This repo's profiling loop: macOS sample <pid> (worked where samply left hex frames), phase-timing via env-gated eprintln! (OCCT_PROFILE=1), cargo build --profile profiling (release + debug symbols, defined in the workspace Cargo.toml) for symbolicated native stacks.
  • Contention shows up as user time, not lock waits: zero ulock/sys with bad thread scaling = cache-line/allocator trouble. Discriminate software vs hardware with the multi-process control (N processes vs N threads of the same work β€” this exposed the OCCT allocator true-sharing bug).
  • Allocation hygiene: with_capacity when size is known; no intermediate .collect() (pass impl Iterator); SmallVec only where measured (the contacts type here β€” kept, measured as noise); memoize expensive derived values in OnceCell fields rather than recomputing per iteration.
  • Allocator: tikv-jemallocator is Linux-only in apps/assembler β€” measured a ~6% loss on macOS. Don't "fix" that gate.
  • #[inline], LTO, codegen-units=1: only with a benchmark proving them.

Tooling

  • cargo build --release -p assembler β€” workspace root; build.rs resolves OCCT via OCCT_PREFIX β†’ cached static build (~/.cache/carbon-occt/) β†’ brew (see apps/assembler/AGENTS.md).
  • Tests: unit in-module; integration in crates/*/tests/ β€” behavioral synthetic-geometry tests (crates/planner/tests/synthetic_plan.rs) are the model: build inputs in code, assert invariants, no fixtures/goldens. Env-gated tests (ASSEMBLER_FIXTURES, ASSEMBLER_ASSEMBLIES) skip silently when unset β€” fine for corpus tests, never for core logic.
  • cargo clippy --all-targets -- -D warnings before committing Rust; #[expect(lint, reason = "...")] over blanket #[allow].

More from crbnos

Other Claude Code skills by this author in the directory.

🌐
1w ago

Agent Browser

Browser automation CLI for AI agents. Use it to navigate pages, fill forms, click buttons, take screenshots, extract data, test web apps, or automate any browser task.
Automation
+0%2.3K325
πŸ”‘
1w ago

Carbon Dev Auth

Authenticates a local browser session against the Carbon ERP dev server using DEV_BYPASS_EMAIL, enabling automated testing and manual verification. Leaves session open for subsequent commands.
Automation
+0%2.3K325
πŸ“š
1w ago

Carbon Docs

Author, edit, or extend Carbon's documentation site β€” a Fumadocs + Next.js app. Use for reader-facing guides, reference pages, and documentation IA. Grounds every claim in source code and follows a warm-paper house style.
Writing
+0%2.3K325
βœ…
1w ago

Check and Commit

Runs a sequence of code quality gates (type generation, formatting, linting, typecheck, tests, build, i18n) on changed files, fixes simple issues, and commits only when all checks pass. Ideal after a code fix, task execution, or manual changes before committing.
Quality
+0%2.3K325
πŸ”„
1w ago

Conductor

Drive a single work item through a doer→gate→judge→keep-or-revert→ledger cycle to a gated PR, unattended. Use for tightly-scoped bugs, usability tweaks, or small features with explicit acceptance criteria.
Automation
+0%2.3K325
πŸ€–
1w ago

Create AGENTS.md

Generates or refreshes AGENTS.md files for Carbon packages and ERP modules by analyzing the actual source code. Ensures every documentation claim is verified against real functions, tables, and exports.
Writing
+0%2.3K325