Not on Product Hunt
Claude Skills
AI Agentssoon
Workflowssoon
Creators

Not on Product Hunt

1,496 curated Claude Skills. We rejected 2,904 so you don't have to.

Categories

DevelopmentMarketingSecurityIntegrationsOperationsLegal

Resources

Submit a SkillSearch SkillsCreatorsSitemapllms.txt

Legal

Privacy PolicyTerms of Service

© 2025 Not on Product Hunt. Not affiliated with Product Hunt.

Built for the Claude community

Sparze ECS Framework Expert is a development Claude Skill built by Neo. Best for: Game developers and systems programmers use this to architect Sparze ECS applications with proper entity lifecycle management, deferred command patterns, and query optimization..

What it does
Build high-performance Entity Component System applications in Zig using Sparze with compile-time safety and performance optimization.
Category
development
Created by
Neo
Last updated
January 5, 2026
developmentadvanced

Sparze ECS Framework Expert

Build high-performance Entity Component System applications in Zig using Sparze with compile-time safety and performance optimization.

Skill instructions


name: sparze description: Expert guidance for Sparze ECS apps including systems, queries, components, resources, events, and performance trade-offs.

Sparze ECS Skill

Expert guidance for building high-performance ECS applications with Sparze.

Core Concepts

World: ECS coordinator with compile-time component, resource, event, and group types.

const World = sparze.World(
    .{ Position, Velocity, Health },     // Components
    .{ DeltaTime, Score },               // Resources
    .{ CollisionEvent },                 // Events
    .{ struct { Position, Velocity } },  // Groups
);

Entity: 32-bit handle [version:16 | index:16]. index selects dense slot; version invalidates stale handles. Use .index, .version, or getIndex() / getVersion(). Create via Entity.init(), serialize with toInt() / fromInt(u32).

Components: Data attached to entities. Tag components (empty structs) use 1 bit per entity.

Resources: Global singletons injected via Resource(T) / ResourceMut(T). Can implement init() / deinit(), or opt out with pub const auto_init = false (manual initialization required). POD resources are zero-initialized for compatibility.

Events: 1-frame delayed, double-buffered communication. Events written in frame N are read in frame N+1.

Docs: @docs/ARCHITECTURE.md, @docs/ENTITY_LIFECYCLE.md

System Functions

System functions use injected parameters and must use commands: anytype for world mutation. Return void or !void.

fn mySystem(
    allocator: std.mem.Allocator,
    movement: Group(struct { Position, Velocity }),
    health: SingleQuery(Health),
    delta: Resource(DeltaTime),
    score: ResourceMut(Score),
    reader: EventReader(CollisionEvent),
    writer: EventWriter(DamageEvent),
    commands: anytype,
) !void {
    // Implementation
}

Commands API

Immediate (returns now):

  • commands.createEntity()
  • try commands.createEntityWith(.{ Position{...}, Velocity{...} })
  • commands.setResource(T, value) / commands.getResource(T) / commands.getResourcePtrMut(T)
  • try commands.initResources(.{ ... })
  • try commands.serializeToFile(path) / try commands.deserializeFromFile(path)

Deferred (applied at world.endFrame()):

  • try commands.addComponent(e, T, value) / try commands.removeComponent(e, T)
  • try commands.addTag(e, T) / try commands.removeTag(e, T)
  • try commands.destroyEntity(e)

Why deferred: avoids invalidating iterators or shifting dense arrays mid-iteration.

Docs: @docs/SYSTEM_PATTERNS.md

Queries

Decision guide:

  • SingleQuery: single component, any frequency
  • Query: multi-component, occasional use
  • Group: multi-component, hot path

SingleQuery(Component)

fn healthSystem(query: SingleQuery(Health)) !void {
    for (query.entities, query.components) |entity, *health| {
        health.hp = @max(0, health.hp);
    }
}

Query(struct { ... })

fn combatSystem(query: Query(struct { Position, Health, ?Shield })) !void {
    for (query.entities) |entity| {
        if (query.filter(entity)) {
            const pos = query.getComponent(entity, Position);
            const health = query.getComponentMut(entity, Health);
            const shield = query.getOptional(entity, Shield);
            _ = pos; _ = health; _ = shield;
        }
    }
}

Group(struct { ... })

const MovementGroup = struct { Position, Velocity };
const World = sparze.World(.{ Position, Velocity }, .{}, .{}, .{ MovementGroup });

fn movementSystem(group: Group(MovementGroup)) !void {
    const positions = group.getMutArrayOf(Position);
    const velocities = group.getArrayOf(Velocity);
    for (positions, velocities) |*pos, vel| {
        pos.x += vel.x;
        pos.y += vel.y;
    }
}

Free(Component): use in groups that do not own a component. Access via group.getComponent(entity, T) instead of array access.

Tag Queries

fn enemySystem(query: TagQuery(struct { Enemy, ?Boss, Exclude(Dead) })) !void {
    for (query.entities) |entity| {
        if (query.filter(entity)) {
            _ = entity;
        }
    }
}

Docs: @docs/QUERY_PATTERNS.md

Query Modifiers

  • Optional (?T): entity may or may not have component
  • Exclude(T): filter out entities with component
  • Free(T): group does not own component; access by lookup

System Organization

Principles:

  • One system, one responsibility
  • Writers run before readers
  • Use events for loose coupling (1-frame delay)
  • Group systems by domain (physics, combat, rendering)

Frame lifecycle:

world.beginFrame();
try world.runSystem(inputSystem);
try world.runSystem(physicsSystem);
try world.runSystem(renderSystem);
try world.endFrame();

Critical: Always call endFrame() to flush deferred commands.

Resources

Initialization options:

  • init() / deinit() for auto-lifecycle
  • pub const auto_init = false for manual setup
  • POD resources are zero-initialized

Safety helpers:

  • isResourceInitialized(T)
  • tryGetResource(T)
  • initResources(.{ ... }) for bulk init

Performance

Fastest to slowest:

  1. Group owned components (getMutArrayOf)
  2. SingleQuery
  3. Group free components (getComponent)
  4. Query

Best practices:

  • Use Group for hot-path systems
  • Use Query for ad-hoc/dynamic access
  • Validate group ownership with World.validateGroups()

Storage notes:

  • Tag components use 1 bit per entity
  • Reserve with getSparseSetPtrMut(T).reserve(capacity)
  • Pagination: 4096 entities per page

Docs: @docs/PERFORMANCE.md, @docs/STORAGE_INTERNALS.md

Quick Reference

| Task | API | |------|-----| | Create entity | commands.createEntity() | | Add component | try commands.addComponent(e, T, value) | | Query single | SingleQuery(Health) | | Query multi | Query(struct { Position, Velocity }) | | Fastest iteration | Group(struct { Position, Velocity }) | | Optional component | Query(struct { Position, ?Sprite }) | | Exclude entities | Query(struct { Enemy, Exclude(Dead) }) | | Read resource | Resource(DeltaTime) | | Write resource | ResourceMut(Score) | | Read events | EventReader(CollisionEvent) | | Write events | EventWriter(DamageEvent) | | Tag iteration | SingleTag(Enemy) |

Documentation Index

  • @docs/ARCHITECTURE.md
  • @docs/QUERY_PATTERNS.md
  • @docs/ENTITY_LIFECYCLE.md
  • @docs/STORAGE_INTERNALS.md
  • @docs/SYSTEM_PATTERNS.md
  • @docs/PERFORMANCE.md
View raw SKILL.md on GitHub

Install

/plugin install sparze-ecs-framework-expert@glassesneo

Requires Claude Code CLI.

Use cases

Game developers and systems programmers use this to architect Sparze ECS applications with proper entity lifecycle management, deferred command patterns, and query optimization.

Reviews

No reviews yet. Be the first to review this skill.

Stats

Installs0
GitHub Stars2
Forks0
LicenseMIT License
UpdatedJan 5, 2026

Creator

N

Neo

@glassesneo

View on GitHub