init repo

This commit is contained in:
2026-04-22 20:55:36 +02:00
commit 0155516457
32 changed files with 7712 additions and 0 deletions

7
.cargo/config.toml Normal file
View File

@@ -0,0 +1,7 @@
[alias]
r = "run"
rr = "run --release --no-default-features"
c = "check"
t = "test"
nt = "nextest run"
cl = "clippy --workspace --all-targets --all-features -- -D warnings"

1
.envrc Normal file
View File

@@ -0,0 +1 @@
use flake

6
.gitignore vendored Normal file
View File

@@ -0,0 +1,6 @@
/target
/result
.direnv
.DS_Store
ai/context/*.md
ai/context/*.txt

45
.opencode/opencode.json Normal file
View File

@@ -0,0 +1,45 @@
{
"$schema": "https://opencode.ai/config.json",
"default_agent": "build",
"instructions": [
"AGENTS.md",
"docs/ai/*.md"
],
"permission": {
"edit": "ask",
"bash": "ask",
"skill": {
"*": "allow"
}
},
"watcher": {
"ignore": [
"target/**",
".git/**",
"ai/context/**"
]
},
"snapshot": true,
"command": {
"context": {
"template": "Read @AGENTS.md and @ai/context/project-context.md. Refresh context if stale by running `!./ai/scripts/build-context.sh`. Summarize current architecture, next milestone, and top risks.",
"description": "Summarize current Bevy project context",
"agent": "plan"
},
"feature": {
"template": "Read @AGENTS.md, @docs/ai/bevy-quick-reference.md, @docs/ai/bevy-project-patterns.md, and @ai/context/project-context.md. Plan and then implement feature: $ARGUMENTS. Before editing, explain files to change, ECS design, and verify commands.",
"description": "Plan and implement small Bevy feature",
"agent": "build"
},
"bug": {
"template": "Read @AGENTS.md, @docs/ai/bevy-debug-playbook.md, and @ai/context/project-context.md. Investigate and fix: $ARGUMENTS. Show likely root cause, patch plan, and verify commands.",
"description": "Fix Bevy bug with root cause first",
"agent": "build"
},
"review": {
"template": "Read @AGENTS.md, @docs/ai/bevy-quick-reference.md, @docs/ai/bevy-project-patterns.md, and @ai/context/project-context.md. Review ECS design and architecture for: $ARGUMENTS. Give strengths, risks, concrete refactor steps.",
"description": "Review Bevy architecture",
"agent": "plan"
}
}
}

View File

@@ -0,0 +1,32 @@
---
name: bevy-architecture
description: Review and improve Bevy project structure, plugin boundaries, and feature isolation
license: MIT
compatibility: opencode
metadata:
stack: bevy
concern: architecture
---
## What I do
- review plugin boundaries
- spot ECS smells
- suggest module split
- suggest state/event/resource boundaries
- keep project workshop-fast
## Smells to flag
- giant systems
- state hidden in many places
- UI mixed with gameplay
- direct coupling across features
- asset logic spread everywhere
## Deliverable
- top strengths
- top risks
- concrete refactor order
- verify commands

View File

@@ -0,0 +1,31 @@
---
name: bevy-debug
description: Debug common Bevy runtime, ECS, asset, input, and scheduling problems
license: MIT
compatibility: opencode
metadata:
stack: bevy
mode: debug
---
## What I do
- narrow likely root causes
- map symptom to file and system
- suggest smallest probe first
- suggest smallest safe fix
- give exact verify commands
## Use when
- app opens but scene blank
- movement or input broken
- UI not updating
- panic or borrow conflict appears
- schedule/state confusion happens
## Rules
- quote exact compiler/runtime error if present
- do not jump to big refactor first
- check camera, assets, queries, states, and schedules

View File

@@ -0,0 +1,41 @@
---
name: bevy-ecs
description: Design clean Bevy ECS layouts with components, resources, events, systems, and states
license: MIT
compatibility: opencode
metadata:
stack: bevy
language: rust
---
## What I do
- turn game idea into ECS parts
- split data across components, resources, and events
- propose system boundaries
- suggest state flow
- keep Bevy code idiomatic and small
## When to use me
Use when:
- new mechanic starts
- code feels like one giant system
- feature needs plugin split
- event vs resource choice unclear
## Output shape
1. goal
2. ECS map
3. file plan
4. patch order
5. verify commands
## Rules
- prefer Bevy built-ins before extra crates
- keep `main.rs` thin
- prefer events for loose coupling
- prefer states for app flow
- keep names specific

View File

@@ -0,0 +1,23 @@
---
name: bevy-ui
description: Build and debug Bevy UI flows for HUD, score, menus, and state-driven screens
license: MIT
compatibility: opencode
metadata:
stack: bevy
area: ui
---
## What I do
- propose HUD/menu structure
- map UI state to resources/events/states
- keep gameplay logic out of UI systems
- suggest update flow for score and status text
## Use when
- adding score counter
- adding pause/menu/game over screen
- fixing stale UI text
- separating HUD from gameplay

98
.vscode/tasks.json vendored Normal file
View File

@@ -0,0 +1,98 @@
{
"version": "2.0.0",
"tasks": [
{
"label": "requirements:check (native)",
"type": "shell",
"command": "bash ./scripts/check-requirements.sh --mode native",
"problemMatcher": []
},
{
"label": "requirements:check (nix)",
"type": "shell",
"command": "bash ./scripts/check-requirements.sh --mode nix-host && nix develop -c bash ./scripts/check-requirements.sh --mode nix-shell",
"problemMatcher": []
},
{
"label": "build:check (native)",
"type": "shell",
"command": "cargo check",
"group": "build",
"problemMatcher": [
"$rustc"
]
},
{
"label": "build:check (nix)",
"type": "shell",
"command": "nix develop -c cargo check",
"problemMatcher": [
"$rustc"
]
},
{
"label": "build:lint (native)",
"type": "shell",
"command": "cargo fmt --all && cargo check && cargo clippy --workspace --all-targets --all-features -- -D warnings",
"problemMatcher": [
"$rustc"
]
},
{
"label": "build:lint (nix)",
"type": "shell",
"command": "nix develop -c bash -lc 'cargo fmt --all && cargo check && cargo clippy --workspace --all-targets --all-features -- -D warnings'",
"problemMatcher": [
"$rustc"
]
},
{
"label": "dev:run (native)",
"type": "shell",
"command": "cargo run",
"problemMatcher": [
"$rustc"
]
},
{
"label": "dev:run (nix)",
"type": "shell",
"command": "nix develop -c cargo run",
"problemMatcher": [
"$rustc"
]
},
{
"label": "dev:watch (native)",
"type": "shell",
"command": "cargo watch -x run",
"problemMatcher": [
"$rustc"
]
},
{
"label": "dev:watch (nix)",
"type": "shell",
"command": "nix develop -c cargo watch -x run",
"problemMatcher": [
"$rustc"
]
},
{
"label": "run:release (native)",
"type": "shell",
"command": "cargo run --release --no-default-features",
"problemMatcher": [
"$rustc"
]
},
{
"label": "run:release (nix)",
"type": "shell",
"command": "nix develop -c cargo run --release --no-default-features",
"problemMatcher": [
"$rustc"
]
}
]
}

78
AGENTS.md Normal file
View File

@@ -0,0 +1,78 @@
# Bevy Game Project Rules
## Mission
Build game features fast, but keep code clean enough to survive workshop iteration.
Target stack:
- Rust `1.95.0`
- Bevy `0.18.1`
- 2D first
- local assets in `assets/`
## Hard rules
- Use Bevy `0.18.1` APIs only.
- Prefer Bevy built-ins before adding third-party crates.
- Keep compile loop short. Small steps. Small diffs.
- No giant god-systems. Split logic into focused systems and plugins.
- Keep rendering, input, gameplay, UI, and debug concerns separate.
- New feature must include:
- code change
- short reason
- how to run
- what to test manually
- After code edits run, in order:
1. `cargo fmt --all`
2. `cargo check`
3. `cargo clippy --workspace --all-targets --all-features -- -D warnings`
- If command fails, quote exact error.
- Do not migrate versions unless asked.
- Do not invent APIs. Check local files first, then docs index in `docs/ai/bevy-source-index.md`.
## Bevy design rules
- App setup in `main.rs` stays thin.
- Put features in plugins under `src/` when project grows.
- Use:
- Components for entity data
- Resources for singleton state
- Events for loose coupling
- States for game flow
- For temporary prototypes, prefer explicit code over macro cleverness.
- Keep startup systems idempotent where possible.
- Use `Name` on important entities in debug-heavy scenes.
- Asset paths relative to `assets/`.
## Architecture defaults
When adding real gameplay, move toward this split:
- `src/game/` core gameplay plugin
- `src/player/` player components + systems
- `src/ui/` UI plugin
- `src/state/` app/game states
- `src/debug/` debug helpers
## Review checklist
Before final answer:
- Is ECS layout sane?
- Are system names specific?
- Are queries minimal?
- Is state transition explicit?
- Is UI separate from gameplay?
- Are commands deferred only where needed?
- Is code Bevy-idiomatic for `0.18.1`?
- Did you list exact run/test commands?
## AI context files
Read when useful:
- `docs/ai/bevy-quick-reference.md`
- `docs/ai/bevy-project-patterns.md`
- `docs/ai/bevy-debug-playbook.md`
- `docs/ai/workshop-scope.md`
- `ai/context/project-context.md`

164
CLAUDE.md Normal file
View File

@@ -0,0 +1,164 @@
# Bevy Nix Template - Detailed Dev Guide
This is the canonical deep guide for newcomers and AI agents working in this repo.
## Project Snapshot
- Purpose: minimal Bevy template for fast workshop iteration with optional local AI workflows.
- Stack:
- Rust `1.95.0` target (via `flake.nix` dev shell)
- Bevy `0.18.1`
- 2D-first project scope
- Current app behavior (`src/main.rs`):
- starts Bevy app with a titled 1280x720 window
- spawns a single `Camera2d`
## Canonical File Map
Authoritative files:
- `AGENTS.md`: coding and architecture rules for this template.
- `Cargo.toml`: Rust package and Bevy dependency configuration.
- `flake.nix`: reproducible Nix development environment.
- `justfile`: daily dev commands.
- `.opencode/opencode.json`: OpenCode command templates and permissions.
- `ai/scripts/*.sh`: local context and llama automation scripts.
- `docs/ai/*.md`: Bevy design and debugging references.
- `src/main.rs`: current game entrypoint.
Generated files:
- `ai/context/project-context.md`: generated by `just context` or `./ai/scripts/build-context.sh`.
- Do not hand-edit this file.
- Regenerate when source/docs change and before context-heavy AI prompts.
## Setup Paths
Recommended path (reproducible):
```bash
nix develop
cargo run
```
Optional host-native path:
```bash
# install rust + tooling yourself, then run
cargo run
```
Run prerequisites checker:
```bash
bash ./scripts/check-requirements.sh --mode native
bash ./scripts/check-requirements.sh --mode nix-host
nix develop -c bash ./scripts/check-requirements.sh --mode nix-shell
```
On macOS, install Xcode Command Line Tools if missing:
```bash
xcode-select --install
```
## Fast Iteration Workflows
Native commands:
```bash
cargo run
cargo watch -x run
cargo fmt --all
cargo check
cargo clippy --workspace --all-targets --all-features -- -D warnings
```
Nix-wrapped equivalents:
```bash
nix develop -c cargo run
nix develop -c cargo watch -x run
nix develop -c cargo fmt --all
nix develop -c cargo check
nix develop -c cargo clippy --workspace --all-targets --all-features -- -D warnings
```
Just shortcuts:
```bash
just run
just watch
just check
just lint
just test
```
## VS Code Tasks
Tasks are defined in `.vscode/tasks.json` and cover:
- requirements checks (native and nix)
- build check (native and nix)
- lint pipeline (`fmt -> check -> clippy`, native and nix)
- dev run/watch (native and nix)
- release run with `--no-default-features` (native and nix)
Use:
```text
Cmd/Ctrl+Shift+P -> "Tasks: Run Task"
```
## AI Workflows
Build/update project context:
```bash
just context
# or
./ai/scripts/build-context.sh
```
Run local llama flows:
```bash
export LLAMA_MODEL=/absolute/path/to/model.gguf
just ai-chat
just ai-plan "add player movement"
just ai-fix "camera jitters on move"
just ai-review "review ECS plugin split"
```
OpenCode config:
- Canonical config: `.opencode/opencode.json`
- It expects `ai/context/project-context.md` to exist or be refreshed.
## Verification Workflow
After Rust code edits, run in this order:
```bash
cargo fmt --all
cargo check
cargo clippy --workspace --all-targets --all-features -- -D warnings
```
For runtime smoke checks:
```bash
cargo run
cargo watch -x run
```
## Troubleshooting
- `Could not resolve host: index.crates.io`:
- network access is required for first dependency download.
- `xcode-select` errors on macOS:
- install CLT with `xcode-select --install`.
- `llama-cli: command not found`:
- install `llama.cpp` tooling or skip local llama commands.
- missing `ai/context/project-context.md`:
- run `just context` before prompts that read project context.

6069
Cargo.lock generated Normal file

File diff suppressed because it is too large Load Diff

20
Cargo.toml Normal file
View File

@@ -0,0 +1,20 @@
[package]
name = "bevy-template-ai"
version = "0.1.0"
edition = "2024"
[dependencies]
bevy = { version = "0.18.1", features = ["dynamic_linking"] }
# Fast enough in dev, not awful to iterate.
[profile.dev]
opt-level = 1
[profile.dev.package."*"]
opt-level = 3
# Shipping profile. No dynamic_linking in release command.
[profile.release]
codegen-units = 1
lto = "thin"
strip = "debuginfo"

86
README.md Normal file
View File

@@ -0,0 +1,86 @@
# Bevy + Local AI Template
Rust `1.95.0` target. Bevy `0.18.1`.
Recommended deep guide: [`CLAUDE.md`](./CLAUDE.md)
## Quickstart
Recommended setup (Nix):
```bash
nix develop
cargo run
```
Host-native setup check:
```bash
bash ./scripts/check-requirements.sh --mode native
```
Nix setup check:
```bash
bash ./scripts/check-requirements.sh --mode nix-host
nix develop -c bash ./scripts/check-requirements.sh --mode nix-shell
```
On macOS, if needed:
```bash
xcode-select --install
```
## Daily Loop
```bash
# run game
cargo run
# auto-rebuild + rerun
cargo watch -x run
# required verification order
cargo fmt --all
cargo check
cargo clippy --workspace --all-targets --all-features -- -D warnings
# tests
cargo test
# refresh generated AI context
just context
```
## AI Context and Local Llama
`ai/context/project-context.md` is generated, not hand-authored.
Refresh it with:
```bash
just context
# or
./ai/scripts/build-context.sh
```
Local llama usage:
```bash
export LLAMA_MODEL=/absolute/path/to/model.gguf
just ai-chat
just ai-plan "add player movement with WASD"
just ai-fix "camera jitters when player moves"
just ai-review "review ECS layout and plugin split"
```
## VS Code Tasks
This repo includes `.vscode/tasks.json` for quick iteration:
- requirements checks (native and nix)
- build check (native and nix)
- lint (`fmt -> check -> clippy`, native and nix)
- run/watch (native and nix)
- release run (`--no-default-features`, native and nix)

15
ai/prompts/fix.md Normal file
View File

@@ -0,0 +1,15 @@
Task type: bug fixing
Read:
- AGENTS.md
- docs/ai/bevy-debug-playbook.md
- ai/context/project-context.md
Then:
- restate bug
- list top 3 likely root causes
- point to exact file/section likely involved
- propose smallest fix first
- show verify commands
- if evidence weak, say what to inspect next
- keep Bevy 0.18.1 APIs only

16
ai/prompts/plan.md Normal file
View File

@@ -0,0 +1,16 @@
Task type: feature planning
Read:
- AGENTS.md
- docs/ai/bevy-quick-reference.md
- docs/ai/bevy-project-patterns.md
- ai/context/project-context.md
Then:
- summarize current architecture
- propose smallest next milestone
- list files to add/edit
- sketch ECS design: components, resources, events, states, plugins
- give ordered patch steps
- give verify commands
- keep Bevy 0.18.1 APIs only

16
ai/prompts/review.md Normal file
View File

@@ -0,0 +1,16 @@
Task type: architecture review
Read:
- AGENTS.md
- docs/ai/bevy-quick-reference.md
- docs/ai/bevy-project-patterns.md
- ai/context/project-context.md
Then:
- identify top 3 strengths
- identify top 5 risks
- call out ECS smells
- suggest plugin split
- suggest resources/events/states to add or remove
- keep advice concrete and patchable
- keep Bevy 0.18.1 APIs only

68
ai/scripts/build-context.sh Executable file
View File

@@ -0,0 +1,68 @@
#!/usr/bin/env bash
set -euo pipefail
mkdir -p ai/context
OUT="ai/context/project-context.md"
{
echo "# Project Context"
echo
echo "Generated: $(date -u +"%Y-%m-%dT%H:%M:%SZ")"
echo
echo "## Repo Tree"
echo
echo '```text'
if command -v tree >/dev/null 2>&1; then
tree -a -I target -I .git
else
echo "[tree not installed, showing file list fallback]"
fd -t f . src docs ai .cargo -E ai/context -E target | sort
fi
echo '```'
echo
echo "## Cargo.toml"
echo
echo '```toml'
cat Cargo.toml
echo '```'
echo
echo "## AGENTS.md"
echo
cat AGENTS.md
echo
echo "## Source Files"
echo
while IFS= read -r file; do
echo "### ${file}"
echo
case "${file}" in
*.rs)
echo '```rust'
cat "${file}"
echo '```'
;;
*.toml)
echo '```toml'
cat "${file}"
echo '```'
;;
*.md)
cat "${file}"
;;
*)
echo '```text'
cat "${file}"
echo '```'
;;
esac
echo
done < <(fd -t f . src docs ai .cargo -E ai/context -E target | sort)
echo "## TODO / FIXME / HACK"
echo
echo '```text'
rg -n "TODO|FIXME|HACK|BUG" . --glob '!target/**' --glob '!ai/context/**' || true
echo '```'
} > "${OUT}"
echo "Wrote ${OUT}"

18
ai/scripts/llama-chat.sh Executable file
View File

@@ -0,0 +1,18 @@
#!/usr/bin/env bash
set -euo pipefail
MODEL="${LLAMA_MODEL:-}"
if [ -z "${MODEL}" ]; then
echo "error: LLAMA_MODEL not set"
echo "export LLAMA_MODEL=/absolute/path/to/model.gguf"
exit 1
fi
./ai/scripts/build-context.sh >/dev/null
exec llama-cli \
-m "${MODEL}" \
-sysf ai/system-prompt.md \
-f ai/context/project-context.md \
-cnv \
-mli

47
ai/scripts/llama-task.sh Executable file
View File

@@ -0,0 +1,47 @@
#!/usr/bin/env bash
set -euo pipefail
MODE="${1:-}"
TASK="${2:-}"
if [ -z "${MODE}" ] || [ -z "${TASK}" ]; then
echo "usage: $0 <plan|fix|review> <task text>"
exit 1
fi
MODEL="${LLAMA_MODEL:-}"
if [ -z "${MODEL}" ]; then
echo "error: LLAMA_MODEL not set"
echo "export LLAMA_MODEL=/absolute/path/to/model.gguf"
exit 1
fi
case "${MODE}" in
plan|fix|review) ;;
*)
echo "error: mode must be one of: plan fix review"
exit 1
;;
esac
./ai/scripts/build-context.sh >/dev/null
TMP="$(mktemp)"
trap 'rm -f "$TMP"' EXIT
{
cat "ai/prompts/${MODE}.md"
echo
echo "User task:"
echo "${TASK}"
echo
echo "Project context follows:"
echo
cat ai/context/project-context.md
} > "${TMP}"
exec llama-cli \
-m "${MODEL}" \
-sysf ai/system-prompt.md \
-f "${TMP}" \
-st

34
ai/system-prompt.md Normal file
View File

@@ -0,0 +1,34 @@
You are local game-dev copilot for Rust + Bevy project.
Goals:
- help build small playable games fast
- preserve clean ECS design
- keep answers grounded in repo files and local docs
- prefer smallest safe next step
Project facts:
- Rust 1.95.0
- Bevy 0.18.1
- workshop setting
- 2D-first scope
- assets in ./assets
- GIMP exists on host, not in Nix shell
Behavior:
- read project context first if present
- propose small diffs
- prefer Bevy built-ins before new crates
- keep main.rs thin
- suggest plugins, resources, events, states when code grows
- quote exact commands to run
- when fixing bug: identify likely root cause, not symptoms only
- when unsure: state uncertainty and list what file or example to inspect next
- never invent Bevy APIs
- do not upgrade dependencies unless asked
Response format:
1. Goal
2. Plan
3. Patch sketch
4. Verify commands
5. Risks

0
assets/.gitkeep Normal file
View File

View File

@@ -0,0 +1,62 @@
# Bevy Debug Playbook
## When build fails
Run:
```bash
cargo check
cargo clippy --workspace --all-targets --all-features -- -D warnings
```
Quote exact compiler error. Fix smallest cause first.
## When game opens but nothing visible
Check:
1. camera spawned?
2. entity has render component?
3. transform in view?
4. asset path correct?
5. window created?
6. alpha / color not invisible?
7. system registered in right schedule/state?
## When movement broken
Check:
- input system runs?
- query matches entity?
- transform or velocity changed?
- another system overwrites transform?
- delta time used correctly?
## When UI broken
Check:
- UI entity spawned?
- text component updated?
- wrong state schedule?
- score resource/event exists?
- UI and gameplay mixed too tightly?
## When architecture feels messy
Refactor by:
- extracting plugin
- moving singleton data into resource
- replacing direct calls with events
- introducing state for flow
- shrinking system queries
## Review output format for AI
When AI reviews code, demand:
1. top 3 bugs
2. top 3 architecture risks
3. concrete patch plan
4. exact commands to verify

View File

@@ -0,0 +1,94 @@
# Bevy Project Patterns
## Start small
For workshop speed, stay in one crate.
When code grows, split by feature modules, not by technical layer only.
Good early structure:
```text
src/
├── main.rs
├── player.rs
├── ui.rs
├── state.rs
└── game.rs
```
Later:
```text
src/
├── main.rs
├── game/
│ ├── mod.rs
│ ├── plugin.rs
│ ├── events.rs
│ └── state.rs
├── player/
│ ├── mod.rs
│ ├── components.rs
│ ├── systems.rs
│ └── plugin.rs
└── ui/
├── mod.rs
├── components.rs
├── systems.rs
└── plugin.rs
```
## Thin main
`main.rs` should mostly:
- create `App`
- add plugins
- init resources
- add states
- run
Business logic lives in feature plugins.
## Plugin boundaries
Each plugin should own:
- components
- resources
- events
- systems
- setup hooks
## Event flow example
Input system -> movement system -> collision system -> score event -> UI system
Good because:
- no direct UI coupling in gameplay code
- each step easy to test and inspect
## State flow example
`Loading -> Menu -> Playing -> GameOver`
Each state should have:
- enter setup
- update systems
- exit cleanup if needed
## Asset handling
- keep asset paths stable
- store handles in resources or components
- preload if startup hitches matter
- keep workshop assets tiny and few
## Debug helpers
Worth adding early:
- `Name` components on important entities
- debug print on critical events
- optional debug plugin
- one place for feature flags and tuning constants

View File

@@ -0,0 +1,112 @@
# Bevy Quick Reference
## Core mental model
Bevy app = plugins + schedules + systems + ECS data.
- **Entity**: ID
- **Component**: data attached to entity
- **System**: function operating on ECS data
- **Resource**: singleton global-ish state
- **Event**: decoupled message
- **State**: app/game phase control
- **Plugin**: feature boundary
## Default 2D startup
Typical minimum:
- add `DefaultPlugins`
- spawn `Camera2d`
- later: sprites, transforms, input systems
## Good first feature order
1. camera
2. player entity
3. movement
4. bounds / collision
5. score / HUD
6. game state
7. win / lose loop
8. juice: audio, particles, animation
## ECS rules
Good:
- data-only components
- small systems
- clear queries
- events for cross-feature signaling
Bad:
- single mega resource for all state
- one system doing input + movement + combat + UI
- hidden state mutation in many places
- coupling features through direct queries everywhere
## Naming
Prefer:
- `Player`
- `Velocity`
- `Health`
- `Score`
- `GameState`
- `spawn_player`
- `move_player`
- `update_score_ui`
Avoid vague names:
- `Data`
- `Info`
- `do_stuff`
- `manager`
## Common patterns
### Resource pattern
Use for global config, score, timers, handles, current run state.
### Event pattern
Use when one system announces and another reacts:
- enemy died
- score changed
- level completed
- damage taken
### State pattern
Use for flow:
- `Loading`
- `Menu`
- `Playing`
- `Paused`
- `GameOver`
### Plugin pattern
Use for feature isolation:
- player
- UI
- combat
- level
## Performance-first habits
- query only data needed
- avoid expensive string churn each frame
- keep UI rebuilds scoped
- avoid asset reloading loops
- prefer change detection / explicit triggers when useful
## Workshop-safe scope
Keep small:
- one-screen loop
- one mechanic
- one UI counter
- one win/lose condition
- one polish pass

View File

@@ -0,0 +1,34 @@
# Bevy Source Index
Use these official sources first.
## Start here
- Quick start setup
- Learn page
- API docs
- Official examples
- Migration guides
- Plugin development page
## Official URLs
- https://bevy.org/learn/quick-start/getting-started/setup/
- https://bevy.org/learn/
- https://docs.rs/bevy
- https://github.com/bevyengine/bevy/tree/latest/examples
- https://bevy.org/news/bevy-0-18/
- https://bevy.org/learn/quick-start/plugin-development/
## Search order for AI
1. local project files
2. `docs/ai/*.md`
3. official examples
4. API docs
5. migration / release notes
## Rule
Do not suggest deprecated Bevy APIs from old blog posts or random tutorials.
Match examples to `0.18.1`.

56
docs/ai/workshop-scope.md Normal file
View File

@@ -0,0 +1,56 @@
# Workshop Scope Map
## Agenda to feature translation
### Day 1
Focus:
- Bevy basics
- ECS basics
- setup
- first app
Project target:
- app boots
- 2D camera
- one visible entity
- one moving entity
### Day 2
Focus:
- player movement
- collision
- mechanics
- UI
- scoring
- polish
Project target:
- main loop playable in one room / one screen
- score counter
- game rule
- fail or win condition
### Day 3
Focus:
- animation
- sound
- extended systems
- free project work
Project target:
- one polish mechanic
- one feedback channel: sound, animation, particles, screen effect
- project cleanup
- final showcase build
## Scope kill list
Cut first if time low:
- procedural generation
- networking
- save system
- complex AI
- plugin rabbit holes
- large asset pipelines
- ECS over-abstraction

96
flake.lock generated Normal file
View File

@@ -0,0 +1,96 @@
{
"nodes": {
"flake-utils": {
"inputs": {
"systems": "systems"
},
"locked": {
"lastModified": 1731533236,
"narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "11707dc2f618dd54ca8739b309ec4fc024de578b",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"type": "github"
}
},
"nixpkgs": {
"locked": {
"lastModified": 1776548001,
"narHash": "sha256-ZSK0NL4a1BwVbbTBoSnWgbJy9HeZFXLYQizjb2DPF24=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "b12141ef619e0a9c1c84dc8c684040326f27cdcc",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixos-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs_2": {
"locked": {
"lastModified": 1744536153,
"narHash": "sha256-awS2zRgF4uTwrOKwwiJcByDzDOdo3Q1rPZbiHQg/N38=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "18dd725c29603f582cf1900e0d25f9f1063dbf11",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixpkgs-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"root": {
"inputs": {
"flake-utils": "flake-utils",
"nixpkgs": "nixpkgs",
"rust-overlay": "rust-overlay"
}
},
"rust-overlay": {
"inputs": {
"nixpkgs": "nixpkgs_2"
},
"locked": {
"lastModified": 1776827647,
"narHash": "sha256-sYixYhp5V8jCajO8TRorE4fzs7IkL4MZdfLTKgkPQBk=",
"owner": "oxalica",
"repo": "rust-overlay",
"rev": "40e6ccc06e1245a4837cbbd6bdda64e21cc67379",
"type": "github"
},
"original": {
"owner": "oxalica",
"repo": "rust-overlay",
"type": "github"
}
},
"systems": {
"locked": {
"lastModified": 1681028828,
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
"owner": "nix-systems",
"repo": "default",
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
"type": "github"
},
"original": {
"owner": "nix-systems",
"repo": "default",
"type": "github"
}
}
},
"root": "root",
"version": 7
}

104
flake.nix Normal file
View File

@@ -0,0 +1,104 @@
{
description = "Bevy + local AI game dev template for macOS with Nix";
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
flake-utils.url = "github:numtide/flake-utils";
rust-overlay.url = "github:oxalica/rust-overlay";
};
outputs = { self, nixpkgs, flake-utils, rust-overlay }:
flake-utils.lib.eachDefaultSystem (system:
let
pkgs = import nixpkgs {
inherit system;
overlays = [ (import rust-overlay) ];
};
lib = pkgs.lib;
rustToolchain = pkgs.rust-bin.stable."1.95.0".default.override {
extensions = [
"rust-src"
"rustfmt"
"clippy"
"rust-analyzer"
];
targets = [
"wasm32-unknown-unknown"
];
};
linuxLibs = lib.optionals pkgs.stdenv.isLinux (with pkgs; [
alsa-lib
libudev-zero
vulkan-loader
wayland
libxkbcommon
xorg.libX11
xorg.libXcursor
xorg.libXi
xorg.libXrandr
]);
in {
devShells.default = pkgs.mkShell {
packages = with pkgs; [
rustToolchain
pkg-config
clang
cmake
git
just
bacon
cargo-edit
cargo-watch
cargo-nextest
nil
nixd
taplo
imagemagick
pngquant
ffmpeg
jq
fd
ripgrep
tree
python3
nodejs_22
libiconv
] ++ linuxLibs;
shellHook = ''
export RUST_SRC_PATH="${rustToolchain}/lib/rustlib/src/rust/library"
export LIBCLANG_PATH="${pkgs.llvmPackages.libclang.lib}/lib"
export CARGO_INCREMENTAL=1
export RUST_BACKTRACE=1
export BEVY_ASSET_ROOT="$PWD/assets"
if [ "$(uname)" = "Darwin" ]; then
if ! xcode-select -p >/dev/null 2>&1; then
echo 'error: Xcode Command Line Tools missing. Run: xcode-select --install'
else
export SDKROOT="$(xcrun --sdk macosx --show-sdk-path 2>/dev/null || true)"
fi
fi
mkdir -p assets ai/context
echo "Bevy + AI shell ready"
echo "rustc: $(rustc --version)"
echo "cargo: $(cargo --version)"
echo "node: $(node --version)"
# Keep user prompt/plugins by switching interactive sessions to system zsh.
# This does not affect `nix develop -c ...` non-interactive commands.
if [ -n "''${PS1:-}" ] && [ -z "''${ZSH_VERSION:-}" ] && [ -z "''${IN_NIX_DEVELOP_SYSTEM_ZSH:-}" ] && [ -x /bin/zsh ]; then
export IN_NIX_DEVELOP_SYSTEM_ZSH=1
export SHELL=/bin/zsh
exec /bin/zsh -i
fi
'';
};
}
);
}

44
justfile Normal file
View File

@@ -0,0 +1,44 @@
set shell := ["bash", "-euo", "pipefail", "-c"]
default:
@just --list
run:
cargo run
watch:
cargo watch -x run
check:
cargo check
test:
cargo test
nextest:
cargo nextest run
lint:
cargo fmt --all
cargo clippy --workspace --all-targets --all-features -- -D warnings
release:
cargo run --release --no-default-features
context:
./ai/scripts/build-context.sh
ai-chat:
./ai/scripts/llama-chat.sh
ai-plan TASK:
./ai/scripts/llama-task.sh plan "{{TASK}}"
ai-fix TASK:
./ai/scripts/llama-task.sh fix "{{TASK}}"
ai-review TASK:
./ai/scripts/llama-task.sh review "{{TASK}}"
tree:
tree -a -I target -I .git

176
scripts/check-requirements.sh Executable file
View File

@@ -0,0 +1,176 @@
#!/usr/bin/env bash
set -euo pipefail
MODE="native"
while [[ $# -gt 0 ]]; do
case "$1" in
--mode)
MODE="${2:-}"
shift 2
;;
*)
echo "usage: $0 --mode <native|nix-host|nix-shell>"
exit 2
;;
esac
done
if [[ -z "${MODE}" ]]; then
echo "error: --mode is required"
exit 2
fi
OS="$(uname -s)"
FAILED=0
print_install_hint() {
local cmd="$1"
if [[ "${OS}" == "Darwin" ]]; then
case "${cmd}" in
nix) echo " install: sh <(curl -L https://nixos.org/nix/install) --daemon" ;;
cargo|rustc|rustup) echo " install: curl https://sh.rustup.rs -sSf | sh" ;;
just) echo " install: brew install just" ;;
rg) echo " install: brew install ripgrep" ;;
fd) echo " install: brew install fd" ;;
tree) echo " install: brew install tree" ;;
cargo-watch) echo " install: cargo install cargo-watch" ;;
cargo-nextest) echo " install: cargo install cargo-nextest --locked" ;;
*) echo " install: use your package manager to install '${cmd}'" ;;
esac
return
fi
case "${cmd}" in
nix) echo " install: sh <(curl -L https://nixos.org/nix/install) --daemon" ;;
cargo|rustc|rustup) echo " install: curl https://sh.rustup.rs -sSf | sh" ;;
just) echo " install: sudo apt update && sudo apt install -y just" ;;
rg) echo " install: sudo apt update && sudo apt install -y ripgrep" ;;
fd) echo " install: sudo apt update && sudo apt install -y fd-find" ;;
tree) echo " install: sudo apt update && sudo apt install -y tree" ;;
cargo-watch) echo " install: cargo install cargo-watch" ;;
cargo-nextest) echo " install: cargo install cargo-nextest --locked" ;;
*) echo " install: use your package manager to install '${cmd}'" ;;
esac
}
require_cmd() {
local cmd="$1"
if command -v "${cmd}" >/dev/null 2>&1; then
echo "ok: ${cmd}"
else
echo "missing: ${cmd}"
print_install_hint "${cmd}"
FAILED=1
fi
}
warn_if_missing() {
local cmd="$1"
if command -v "${cmd}" >/dev/null 2>&1; then
echo "ok(optional): ${cmd}"
else
echo "missing(optional): ${cmd}"
print_install_hint "${cmd}"
fi
}
check_xcode_clt() {
if [[ "${OS}" != "Darwin" ]]; then
return
fi
if xcode-select -p >/dev/null 2>&1; then
echo "ok: xcode-command-line-tools"
else
echo "missing: xcode-command-line-tools"
echo " install: xcode-select --install"
FAILED=1
fi
}
print_context_note() {
if [[ -f "ai/context/project-context.md" ]]; then
echo "ok: ai/context/project-context.md exists (generated file)"
else
echo "info: ai/context/project-context.md is generated and currently missing"
echo " generate with: just context"
echo " or: ./ai/scripts/build-context.sh"
fi
}
check_native() {
echo "mode: native"
require_cmd cargo
require_cmd rustc
require_cmd just
require_cmd rg
require_cmd fd
require_cmd tree
if command -v rustup >/dev/null 2>&1; then
if rustup component list --installed | rg -q "^rustfmt"; then
echo "ok: rustup component rustfmt"
else
echo "missing: rustup component rustfmt"
echo " install: rustup component add rustfmt"
FAILED=1
fi
if rustup component list --installed | rg -q "^clippy"; then
echo "ok: rustup component clippy"
else
echo "missing: rustup component clippy"
echo " install: rustup component add clippy"
FAILED=1
fi
else
echo "missing: rustup"
print_install_hint rustup
FAILED=1
fi
warn_if_missing cargo-watch
warn_if_missing cargo-nextest
check_xcode_clt
print_context_note
}
check_nix_host() {
echo "mode: nix-host"
require_cmd nix
check_xcode_clt
}
check_nix_shell() {
echo "mode: nix-shell"
require_cmd cargo
require_cmd rustc
require_cmd just
require_cmd rg
require_cmd fd
require_cmd tree
require_cmd cargo-watch
require_cmd cargo-nextest
check_xcode_clt
print_context_note
}
case "${MODE}" in
native) check_native ;;
nix-host) check_nix_host ;;
nix-shell) check_nix_shell ;;
*)
echo "error: unknown mode '${MODE}'"
echo "usage: $0 --mode <native|nix-host|nix-shell>"
exit 2
;;
esac
if [[ "${FAILED}" -ne 0 ]]; then
echo "requirements check: FAILED"
exit 1
fi
echo "requirements check: OK"

19
src/main.rs Normal file
View File

@@ -0,0 +1,19 @@
use bevy::prelude::*;
fn main() {
App::new()
.add_plugins(DefaultPlugins.set(WindowPlugin {
primary_window: Some(Window {
title: "Bevy Template AI".into(),
resolution: (1280, 720).into(),
..default()
}),
..default()
}))
.add_systems(Startup, setup)
.run();
}
fn setup(mut commands: Commands) {
commands.spawn(Camera2d);
}