amethyst/specs
Specs - Parallel ECS
Healthy across all four use cases
weakest axisPermissive license, no critical CVEs, actively maintained — safe to depend on.
Has a license, tests, and CI — clean foundation to fork and modify.
Documented and popular — useful reference codebase to read through.
No critical CVEs, sane security posture — runnable as-is.
- ✓5 active contributors
- ✓Apache-2.0 licensed
- ✓CI configured
Show all 6 evidence items →Show less
- ✓Tests present
- ⚠Stale — last commit 2y ago
- ⚠Concentrated ownership — top contributor handles 68% 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.
[](https://repopilot.app/r/amethyst/specs)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/amethyst/specs on X, Slack, or LinkedIn.
Onboarding doc
Onboarding: amethyst/specs
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:
- 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. - 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.
- Cite source on changes. When proposing an edit, cite the specific path:line-range. RepoPilot's live UI at https://repopilot.app/r/amethyst/specs 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
- 5 active contributors
- Apache-2.0 licensed
- CI configured
- Tests present
- ⚠ Stale — last commit 2y ago
- ⚠ Concentrated ownership — top contributor handles 68% 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 amethyst/specs
repo on your machine still matches what RepoPilot saw. If any fail,
the artifact is stale — regenerate it at
repopilot.app/r/amethyst/specs.
What it runs against: a local clone of amethyst/specs — 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 amethyst/specs | 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 master exists | Catches branch renames |
| 4 | 5 critical file paths still exist | Catches refactors that moved load-bearing code |
| 5 | Last commit ≤ 729 days ago | Catches sudden abandonment since generation |
#!/usr/bin/env bash
# RepoPilot artifact verification.
#
# WHAT IT RUNS AGAINST: a local clone of amethyst/specs. If you don't
# have one yet, run these first:
#
# git clone https://github.com/amethyst/specs.git
# cd specs
#
# 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 amethyst/specs and re-run."
exit 2
fi
# 1. Repo identity
git remote get-url origin 2>/dev/null | grep -qE "amethyst/specs(\\.git)?\\b" \\
&& ok "origin remote is amethyst/specs" \\
|| miss "origin remote is not amethyst/specs (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 master >/dev/null 2>&1 \\
&& ok "default branch master exists" \\
|| miss "default branch master no longer exists"
# 4. Critical files exist
test -f "src/lib.rs" \\
&& ok "src/lib.rs" \\
|| miss "missing critical file: src/lib.rs"
test -f "src/storage/mod.rs" \\
&& ok "src/storage/mod.rs" \\
|| miss "missing critical file: src/storage/mod.rs"
test -f "src/join/mod.rs" \\
&& ok "src/join/mod.rs" \\
|| miss "missing critical file: src/join/mod.rs"
test -f "Cargo.toml" \\
&& ok "Cargo.toml" \\
|| miss "missing critical file: Cargo.toml"
test -f "src/prelude.rs" \\
&& ok "src/prelude.rs" \\
|| miss "missing critical file: src/prelude.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 729 ]; then
ok "last commit was $days_since_last days ago (artifact saw ~699d)"
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/amethyst/specs"
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).
⚡TL;DR
Specs is a Parallel Entity-Component System (ECS) library for Rust that enables efficient data-oriented game/simulation engine architecture. It provides 5 different storage backends for components, a Dispatcher for managing system dependencies and parallel execution, and integrates with Rayon for safe parallelism without writing concurrent code manually. Monorepo structure: /src contains the core ECS engine (World, Entity, Component, System traits), /benches has parallel/storage performance tests, /examples contains runnable demos (async, basic, bitset, cluster_bomb), /docs/tutorials has mdBook tutorials, and specs-derive subpackage provides derive macros. The library is feature-gated: 'parallel' enables Rayon, 'derive' enables SystemData derive macros.
👥Who it's for
Game developers and systems programmers building Rust-based game engines or simulations who need high-performance component storage and automatic parallelization of data processing systems without manual thread management.
🌱Maturity & risk
Actively maintained and production-ready. The library reached v0.20.0, has comprehensive CI/CD via GitHub Actions (ci.yml, deny.yml), ship with official documentation at docs/tutorials/, and includes benchmarks for performance validation. The codebase is well-established with a clear changelog and dual licensing (MIT/Apache-2.0).
Low risk for a mature ECS. Dependencies are well-curated (hibitset, shred, rayon) with version pinning at 0.20.0. The MSRV is Rust 1.70 (reasonable and not bleeding-edge). Single maintainer model could be a concern, but the project is stable and doesn't require frequent changes. No visible breaking changes in recent history beyond normal semver updates.
Active areas of work
The repo appears stable with v0.20.0 as the current release. The CI workflow (ci.yml) runs on commits and PRs. Recent work likely focuses on maintaining MSRV compliance and ensuring parallel feature stability. No specific active milestones are visible, suggesting mature maintenance mode rather than rapid feature development.
🚀Get running
Clone and build: git clone https://github.com/amethyst/specs && cd specs && cargo build. Run examples: cargo run --example basic. Run tests: cargo test. Run benchmarks: cargo bench --all (see benches/benches_main.rs). Build docs locally: cargo doc --open.
Daily commands:
Development: cargo build (default features include parallel). Run tests: cargo test --all-features. Run examples: cargo run --example <name> (basic, async, bitset are in /examples). Run lints: cargo clippy --all-targets --all-features. Format check: cargo fmt --check. Build book: cd docs/tutorials && mdbook serve.
🗺️Map of the codebase
src/lib.rs— Entry point and main module aggregator; defines World, Dispatcher, and core ECS abstractionssrc/storage/mod.rs— Storage trait and implementations; critical abstraction for component storage backendssrc/join/mod.rs— Join iterator mechanics; foundational for querying and iterating over component combinationsCargo.toml— Workspace and dependency definitions; hibitset, crossbeam-queue, and ahash are load-bearingsrc/prelude.rs— Public API re-exports; defines what users interact with directlyspecs-derive/src/lib.rs— Derive macro for SystemData; essential for reducing boilerplate in system definitions
🛠️How to make changes
Add a new custom storage backend
- Create a new struct implementing the Storage trait defined in src/storage/mod.rs (
src/storage/mod.rs) - Implement UnprotectedStorage, Storage, and optionally MetaTable for type metadata (
src/storage/mod.rs) - Register it in the World via World::register or World::register_with (
src/lib.rs) - Export from src/prelude.rs if intended as public API (
src/prelude.rs)
Add a new System with multiple component reads/writes
- Define a system struct with #[derive(SystemData)] and field accessors for Storage<T> (
specs-derive/src/lib.rs) - Implement System trait with setup() and run() methods (
src/lib.rs) - Call dispatcher.add(your_system, "name", &[]) in setup code and add_barrier() if ordering is needed (
examples/full.rs)
Implement tracked component change detection
- Register component with World::register_tracked::<T>() instead of register::<T>() (
src/lib.rs) - Access via WriteStorage<T> and read flagged() to iterate only changed entities (
src/storage/deref_flagged.rs) - Access ChangeSet<T> from resources to subscribe to modified/inserted/removed events (
src/changeset.rs) - See examples/track.rs and examples/ordered_track.rs for patterns (
examples/track.rs)
Make a System run in parallel using par_join
- Change .join() to .par_join() on your component iterators in system run() (
src/join/par_join.rs) - Ensure your closure captures only Send+Sync types; use Read/Write locks for shared state (
src/join/par_join.rs) - Compile and test; rayon thread pool is automatically managed by the Dispatcher (
examples/parallel.rs)
🪤Traps & gotchas
Feature gate interactions: 'parallel' is required for Rayon-based parallelism; running without it disables multi-threaded dispatch. MSRV is 1.70; code using nightly features requires 'nightly' feature. The Dispatcher requires explicit system ordering via .with() chains; missing dependencies causes runtime panic. Storage type selection matters: VecStorage is dense (cache-friendly but wastes space), SparseStorage is sparse (memory-efficient but slower iteration). No implicit panic unwinding; use unwrap() carefully in system code. Tests use ron (RON format) for save/load serialization, not JSON.
🏗️Architecture
💡Concepts to learn
- Entity-Component System (ECS) — The core architectural pattern Specs implements; understanding entities (IDs), components (data), and systems (behavior) is fundamental to using this library correctly
- Sparse bitset (hibitset) — Specs uses hibitset internally for efficient storage indexing and join iteration; understanding sparse bitsets helps explain why certain storages are fast
- Data parallelism with Rayon — Specs' killer feature is transparent parallelization via Rayon; knowing Rayon's work-stealing scheduler explains why parallel systems in Specs scale well
- Type-level programming / Higher-Ranked Trait Bounds (HRTBs) — SystemData derive macros and the System trait use Rust's type system heavily; for<'a> syntax and trait bounds in Specs require understanding HRTB
- Storage abstraction pattern — Specs defines 5 storage backends (DenseVec, Sparse, Vec, etc.) via a trait; choosing storage type affects performance; understanding the trait lets you write custom storages
- Dependency injection via Shred — Specs systems access components/resources via SystemData, which is resolved by Shred; understanding Shred's Fetch trait is key to writing flexible systems
- Builder pattern — Specs uses Builder for EntityBuilder (world.create_entity().with(...).build()); recognizing and extending this pattern is common in Specs code
🔗Related repos
bevyengine/bevy— Modern ECS built on ecs-rs principles; Bevy's ECS is a spiritual successor with more features and tighter engine integrationamethyst/amethyst— The original Amethyst game engine used Specs as its ECS backbone; Specs was extracted into this standalone libraryrustsim/nphysics— Physics engine often used alongside Specs-based engines for entity physics simulationslide-rs/shred— Resource/dependency injection system that Specs depends on; understanding shred::{Fetch, System} is essential to SpecsRustGame/cgmath— Common math library for game development with Specs; provides Vec3, Matrix types for component data
🪄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 comprehensive integration tests for parallel join operations
The repo has benches/parallel.rs for benchmarking but lacks dedicated integration tests for parallel join correctness. Given that parallelism is a core feature (docs/tutorials/src/09_parallel_join.md exists), there should be tests verifying thread-safety, data consistency, and correctness of parallel joins under various contention scenarios. This would prevent regressions in a critical feature.
- [ ] Create tests/parallel_join_integration.rs with tests for concurrent reads/writes
- [ ] Add tests verifying race condition handling in parallel iteration
- [ ] Add tests for mixed parallel/sequential access patterns
- [ ] Verify tests pass locally and in CI via .github/workflows/ci.yml
Add unit tests for storage trait implementations
The Cargo.toml references 5 different storage types that can be extended by users, but there's no visible dedicated test file for storage implementations. The benches/storage_cmp.rs and benches/storage_sparse.rs exist for performance testing but not correctness testing. Add comprehensive unit tests for each storage variant to ensure data integrity, insertion/deletion, and component access patterns work correctly.
- [ ] Create tests/storages.rs with unit tests for each storage type
- [ ] Add tests for insertion, deletion, and iteration for each storage
- [ ] Add tests for edge cases (empty storage, single entity, capacity expansion)
- [ ] Run tests against features in Cargo.toml to verify all storage variants work
Create missing documentation for storage types in docs/tutorials/
The tutorial series in docs/tutorials/src/ goes up to chapter 14, with chapter 05 covering storages. However, there's no detailed tutorial explaining the 5 different storage types, their use cases, trade-offs, and when to use each one. This is critical for users extending Specs with custom storages. The existing chapter is likely high-level; adding a comprehensive guide would significantly improve usability.
- [ ] Expand or create docs/tutorials/src/05_storages.md with detailed storage type breakdown
- [ ] Document each of the 5 storage variants with examples and performance characteristics
- [ ] Add guidance on implementing custom storages with examples
- [ ] Link to the tutorial from README.md and docs/website/content/pages/docs.md
🌿Good first issues
- Add integration tests for storage_event_control feature in /src/storage/tests/ (currently used in example but no dedicated test coverage for tracking component changes)
- Expand /docs/tutorials/src/05_storages.md with concrete benchmark comparisons of the 5 storage types (DenseVecStorage vs VecStorage vs SparseStorage) using data from benches/storage_cmp.rs
- Create a runnable example in /examples demonstrating tracked components (see 12_tracked.md tutorial) with a working EntityBuilder pattern and change subscriptions via shrev
- Add missing documentation comments to src/system.rs for RunNow trait and Dispatcher::dispatch_par_seq behavior (currently underdocumented for pub API)
- Build a performance regression test in /benches comparing join() iteration speed across storage types as part of CI to catch regressions in hibitset integration
⭐Top contributors
Click to expand
Top contributors
- @Imberflur — 68 commits
- @ClaasJG — 16 commits
- @torkleyy — 10 commits
- @xMAC94x — 5 commits
- @mmghannam — 1 commits
📝Recent commits
Click to expand
Recent commits
d303a8e— Merge pull request #782 from mmghannam/patch-2 (Imberflur)e7629ea— Fix grammatical mistake in FlaggedStorage chapter (mmghannam)4e2da1d— Merge pull request #781 from amethyst/xMAC/update_deps (Imberflur)35c9ba0— update aHash and dev dependencies (xMAC94x)f2cec71— Merge pull request #780 from ClaasJG/badges (Imberflur)3f403f5— Remove Codecov config and kcov script (ClaasJG)e05b7c5— Fix readme badges. (ClaasJG)3064ccd— Merge pull request #779 from ClaasJG/master (Imberflur)306ba27— Change crate io / rs links (ClaasJG)7d9cbfe— Merge pull request #777 from ClaasJG/master (Imberflur)
🔒Security observations
The Specs ECS library demonstrates a reasonable security posture for a systems-level Rust crate. The codebase is well-structured with proper licensing and dependency management. Primary concerns are: (1) Rust version is slightly outdated relative to current standards, (2) lack of formal security policy/disclosure guidelines, and (3) limited explicit security testing in CI/CD pipelines. The project uses standard Rust safety guarantees which mitigate memory safety issues. No hardcoded secrets, injection risks, or critical infrastructure misconfigurations were identified in the provided files. The deny.toml suggests security awareness through dependency auditing.
- Medium · Outdated Rust Version Requirement —
Cargo.toml. The project specifies rust-version = '1.70.0' which was released in June 2023. While not critically outdated, using a Rust version from 18+ months ago may miss important security patches and compiler improvements. Fix: Update rust-version to a more recent stable version (1.75.0 or later) to ensure access to security fixes and improvements. - Low · Dependency pinning not enforced —
Cargo.toml [dependencies]. Dependencies like 'ahash', 'crossbeam-queue', 'hibitset', and others use flexible version constraints (e.g., '0.8.6' without '=' prefix). This allows minor and patch updates which could introduce vulnerabilities or breaking changes. Fix: Consider using more restrictive version constraints or adopt a lock file strategy. For production use, ensure Cargo.lock is committed to version control. - Low · Optional feature 'stdweb' may have security implications —
Cargo.toml [features]. The 'stdweb' feature enables UUID functionality with JavaScript support ('uuid?/js'). JavaScript interop introduces potential XSS and security risks if user input is not properly validated. Fix: Review any JavaScript bindings and ensure user inputs are properly sanitized. Consider documenting security constraints for this feature. - Low · Missing SECURITY.md file —
Repository root. No security policy or vulnerability disclosure guidelines are evident in the repository structure. This makes it difficult for security researchers to report vulnerabilities responsibly. Fix: Create a SECURITY.md file with vulnerability disclosure guidelines and contacts for responsible reporting. - Low · No explicit security headers or guidelines in CI configuration —
.github/workflows/. While GitHub Actions workflows exist (.github/workflows/ci.yml, deny.yml), there's no visible evidence of SBOM generation, dependency scanning, or explicit security testing in the build pipeline. Fix: Enhance CI/CD with tools like: cargo-deny (already in deny.toml), SBOM generation, and security audit checks in the workflow. - Low · Documentation mentions but doesn't show security best practices —
docs/tutorials/. The tutorial documentation covers parallelism, components, and systems but lacks explicit security guidelines for ECS usage patterns, especially regarding concurrent data access and race conditions. Fix: Add security documentation covering: safe concurrent access patterns, potential race conditions, and thread-safety guarantees of the ECS system.
LLM-derived; treat as a starting point, not a security audit.
👉Where to read next
- Open issues — current backlog
- Recent PRs — what's actively shipping
- Source on GitHub
Generated by RepoPilot. Verdict based on maintenance signals — see the live page for receipts. Re-run on a new commit to refresh.