Skip to content

Latest commit

 

History

History
143 lines (107 loc) · 7.51 KB

File metadata and controls

143 lines (107 loc) · 7.51 KB

CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

Project Overview

Enu is a 3D sandbox environment for creating and exploring voxel worlds using a Logo-inspired programming API. It's built with Nim and the Godot game engine (v3.5), enabling users to program interactive 3D environments using Nim scripts that run in the Nim VM.

Build Commands

Do it the normal way

Prefer the standard, supported path over hand-wiring. Builds, submodules, setup, and dependency management go through the built-in nim/atlas tasks (nim prereqs, nim build, nim import_assets, atlas install, ...). Don't shell out to scons, hand-git clone submodules, or symlink/copy prebuilt artifacts (the Godot binary, deps/, vmlib/stdlib, app/.import, ...) from another checkout to skip a step — those shortcuts drift from what real users and CI do, hide build breakage, and entangle checkouts. Lock files are regenerated by their tool, never edited by hand. Deviate only for a specific, stated reason, and prefer fixing the task over working around it.

Setup

  • atlas install && atlas rep - Install dependencies (first-time setup)
  • nim prereqs - Build Godot, download fonts, generate API bindings and stdlib

Dependency Management (Atlas)

  • atlas.lock pins exact dependency versions
  • atlas pin <package> - Update lock file for a specific package after changing its version in deps/
  • atlas install - Install dependencies from lock file
  • atlas rep - Regenerate nim.cfg paths from lock file
  • When changing dependencies in enu.nimble, run atlas install && atlas pin to update the lock file

Generated Artifacts

Never manually edit files that are meant to be produced by tools (lock files, sentinel files, zip archives, etc.), even if you know how to make the required changes. We need to verify our tools work correctly and eliminate potential failure vectors. If a tool isn't producing the expected output, investigate why. Confirm with the user before making any exceptions.

Core Development Commands

  • nim build - Build the main application (required after code changes)
  • nim start - Run Enu in development mode
  • nim build_and_start - Build and run in one command
  • nim edit - Open project in Godot editor

Distribution and Packaging

  • nim dist - Build complete distribution package for current platform
  • nim dist_prereqs - Build debug/release Godot versions and fonts
  • nim dist_package - Package distribution binaries

Testing and Documentation

  • nim test - Run the fast default tests (unit + VM) — use while iterating
  • nim test_all - Run the full suite (unit + VM + world + MCP) — before opening a PR
  • nim test_unit - Run unit tests
  • nim test_vm - Run VM script tests
  • nim test_world - Run in-world tests (boots Godot)
  • nim test_mcp - Run MCP integration tests (launches a private Enu)
  • nim docs - Build documentation using nimibook
  • nim clean - Remove build artifacts

Relevant tests must pass before calling a feature done.

Platform-Specific

  • nim ios - Build iOS package
  • nim ios_prereqs - Build Godot for iOS (requires macOS)

Cross-Architecture Builds (Linux)

Pass amd64 or arm64 to nim prereqs to set the target architecture. See docs/notes/linux-cross-compile.md for detailed setup instructions and required packages.

Architecture

Directory Structure

Core Application (src/)

  • src/enu.nim - Entry point that imports all UI and node components
  • src/core.nim - Core utilities, globals, and common imports
  • src/game.nim - Main game loop and Godot integration
  • src/types.nim - Type definitions for game state, tools, and model flags
  • src/models/ - Data models (bots, builds, players, signs, units, colors, ground)
  • src/controllers/ - Game logic controllers (node and script controllers)
  • src/ui/ - UI components (editor, console, toolbar, settings, etc.)
  • src/nodes/ - Godot node wrappers (player, bot, build, ground, sign nodes)

Virtual Machine Environment (vmlib/)

  • vmlib/enu/ - Enu-specific API for scripts (bots, builds, loops, state machine)
  • vmlib/stdlib/ - Copy of Nim stdlib for VM execution (auto-generated, don't modify)
  • vmlib/worlds/ - Default world templates and tutorials

Godot Integration (app/)

  • app/project.godot - Godot project configuration
  • app/scenes/ - Godot scene files (.tscn)
  • app/components/ - Godot node scripts (.gdns) and scenes
  • app/textures/, app/materials/, app/shaders/ - Game assets

Build System

  • generated/ - Auto-generated Godot API bindings (created by build process)
  • vendor/ - Godot engine submodule
  • tools/build_helpers.nim - Build automation utilities

Key Concepts

Dual Type System: The project has two parallel type systems:

  • Types in src/ for the main application
  • Corresponding types in vmlib/enu/ for VM scripts
  • These represent the same objects but in different contexts

VM Integration: User scripts run in the Nim VM, isolated from the main application. The VM has access to a curated API through vmlib/enu/.

Godot Binding: Uses nim-godot with auto-generated bindings from Godot 3.5 API. Use snake_case when calling these bindings.

Model-View Architecture:

  • Models handle data and state (using model_citizen library)
  • Controllers manage game logic and coordinate between models and UI
  • UI components handle presentation and user interaction

Casing Conventions

This project follows Ruby-like casing conventions. Nim is style-insensitive for identifiers (ignoring case and underscores), so these are style guidelines rather than compiler requirements:

  • Types: UpperCamelCase (e.g., VoxelRenderer, GameState, Build)
  • Enum values: SCREAMING_SNAKE_CASE (e.g., ERASER, BLUE, CODE_MODE, PLAYING)
  • Constants: SCREAMING_SNAKE_CASE (e.g., CHUNK_DIM, ACTION_COLORS, IR_BLACK)
  • Everything else: snake_case (procs, variables, fields, parameters, etc.)
  • Third-party identifiers starting with lowercase: use snake_case (e.g., writeVu64write_vu64)

Only use lowerCamelCase when snake_case doesn't work, which should only happen with third-party macros that don't properly normalize identifiers.

Additional Coding Style Rules

  1. Naming Conventions: Never use camelCase for Nim code. Enu strictly uses snake_case for everything (variables, procs, types in some parts, but standard Nim types are strictly PascalCase).
  2. Exceptions: Do not use newException(ExceptionType, "msg"). Use the helper method ExceptionType.init("msg") (e.g., ValueError.init("Circular dependency detected")).

Important Notes

  • Use nim build to verify changes compile correctly
  • The project uses ZenContext for metrics and threading
  • Scripts are Logo-inspired but use Nim syntax
  • World data is stored as JSON with accompanying Nim scripts
  • If you're not on main or a 0.x branch, try to keep a clean history. Prefer rebasing and ammending commits to keep work in logical chunks and --force-with-lease push them to origin. Confirm with the user before pulling.
  • Never include "Generated by Claude", "Co-Authored-By: Claude", or similar attribution in commits. Keep commit messages concise. Try not to include details that are obvious by quickly looking at the diff.
  • If rebasing or squashing commits, confirm with the user before merging 10 or more commits.
  • Avoid nil checks, unless there is a known, non-bug reason why something could be nil. Asserting something isn't nil is fine.
  • Things that are fairly obvious shouldn't have comments.