Skip to content
hikari
RenderingEditorAIToolchainDocumentation
GitHub
hikari

© 2026 Flying Rat Studio.
All rights reserved.

Explore the engineDocumentationContributorsLicenseBack to top
Documentation / Guides
Browse docs
Overview
Tutorials16
OverviewFirst game projectFirst entityAuthored user_data and the inspectorFirst mesh and materialFirst physics body and triggerFirst character controllerFirst session servicesFirst UIFirst input actionFirst messagesPlay, Edit, and scenesFirst runtime spawnFirst motionFirst skeletal animationAssets in Play (soft refs and hot reload)Dynamic editor recompile
Guides16
OverviewDevelopment guideGameplay APIChoosing component storageBuild and packagingProject filePluginsHikari Plugin APIData-driven content, JSON, and pathsScripting with KawaShader authoringTime of dayUser interfaceUI layoutUI widgetsMigration from Unity / UnrealActor and component lifecycle
Systems28
OverviewArchitectureApplication lifecycleFrontends and driversPlatforms and supportSession services and cross-scene stateScenes and gameplayActor communication (hi.actors)Game-facing refsSave / replication wire versionCoordinate space and camera conventionsRenderingRenderer architecture mapFrame governorGPU particlesVisual ZonesVolumetric mediaInputAudioPhysicsMotion KitTemporal KitAssets and ShinraPrefabsAsset residencyAsset formats (Shinra pipeline)UI and editorEditor asset hot reloadEditor Project Selector
Language reference2
OverviewAkari language referenceKawa language reference
Engine overview
Start exploring
  • No matching sections. Try fewer words or another topic.
NavigateEnter Openesc Close
Overview
Tutorials16
OverviewFirst game projectFirst entityAuthored user_data and the inspectorFirst mesh and materialFirst physics body and triggerFirst character controllerFirst session servicesFirst UIFirst input actionFirst messagesPlay, Edit, and scenesFirst runtime spawnFirst motionFirst skeletal animationAssets in Play (soft refs and hot reload)Dynamic editor recompile
Guides16
OverviewDevelopment guideGameplay APIChoosing component storageBuild and packagingProject filePluginsHikari Plugin APIData-driven content, JSON, and pathsScripting with KawaShader authoringTime of dayUser interfaceUI layoutUI widgetsMigration from Unity / UnrealActor and component lifecycle
Systems28
OverviewArchitectureApplication lifecycleFrontends and driversPlatforms and supportSession services and cross-scene stateScenes and gameplayActor communication (hi.actors)Game-facing refsSave / replication wire versionCoordinate space and camera conventionsRenderingRenderer architecture mapFrame governorGPU particlesVisual ZonesVolumetric mediaInputAudioPhysicsMotion KitTemporal KitAssets and ShinraPrefabsAsset residencyAsset formats (Shinra pipeline)UI and editorEditor asset hot reloadEditor Project Selector
Language reference2
OverviewAkari language referenceKawa language reference
Engine overview
Guides8 min read

Development guide

On this page
On this pageRead before changingEditor syntax highlightingChange by seamEngine extension manifestsProduct Zig std (hikari_std)ValidationNative C / ObjC / C++ style (Metal + D3D12)Error and allocation policyDocumentation policy Back to top

Read before changing

Read the closest AGENTS.md before changing a subsystem. The root guide describes repository-level build/platform rules; engine, Kaji, Kawa, Shinra, and physics packages have local constraints.

New to game packages? Start with Tutorials (entity → session → UI → input → messages → Play/Edit), then return here for change seams.

Paths that look alike: see the naming glossary (frontend vs frontends, scenes/ vs assets/scenes/, assets/ vs resources/, SDK vs game_api, sample game vs standalone_game).

Editor syntax highlighting

VS Code-compatible grammars for Akari (.akari) and Kawa (.kawa) live in tools/vscode-extensions/. They also load in Cursor, VSCodium, Windsurf, and other editors that use the VS Code extension format.

sh
tools/vscode-extensions/install.sh          # macOS / Linux
tools/vscode-extensions/uninstall.sh
# tools/vscode-extensions/install.ps1       # Windows
# tools/vscode-extensions/uninstall.ps1

tools/nvim-plugins/install.sh               # Neovim / Vim packpath
tools/nvim-plugins/uninstall.sh
# tools/nvim-plugins/install.ps1
# tools/nvim-plugins/uninstall.ps1

Reload the editor window (or restart Neovim) afterward.

Change by seam

ChangePrimary seam
Game-facing APIsrc/hikari/sdk/src/hikari_game.zig
Product Zig std (threads, heap, Io, …)src/hikari/sdk/src/std/root.zig — always const std = @import("hikari_std") (see below)
Game editor chrome extensionssdk/src/editor_contrib.zig (hi.editor, -Deditor-contrib) + host editor/game_contrib.zig / editor/contrib.zig (docs)
Source-composed pluginsProject hikari.plugins.json, package hikari.plugin.json, SDK build glue src/hikari/sdk/build/plugins/, generated hikari-plugin-artifacts.json (guide, design)
UI / gameplay motionsrc/hikari/sdk/src/motion/ (Motion Kit)
Timers / delayssrc/hikari/sdk/src/temporal/ (Temporal Kit)
Game configurationsdk/src/project_config.zig, engine src/config.zig (configs/), game root.zig
Frame/runtime behaviorruntime_session.zig
CPU profiler / GPU markersprofiler.zig; Kaji --profiler-timing / --profiler-timing:modules=; runtime Recording (default off) + optional editor/entity/message timing via editor Profiler tab / World.profiler_overlay (UI and editor)
Graphics validation / DRED / GPU-based validationKaji --d3d12-* / --metal-* (aliases): -debug-layer defaults on in debug, -trace and -gbv off — all build-time, all usable in release (build and packaging)
CPU/GPU residency diagnosticsassets/asset_store/diagnostics.zig, graphics/residency/gpu_residency.zig; compile with Kaji --profiler-residency=cpu, gpu, or cpu+gpu (default off). Core lifetime management is unconditional (asset residency)
Backend replacementbackend/registry.zig and type-erased contract; dynamic dylib roots in backend/modules/
Offline tools / benchesEngine: src/hikari/src/tools/ (entity_bench). Script cook: src/kawa/tools/kawac → bin/kawa/<host-arch>/kawac
Audio (cmds → worker → device mix)src/hikari/src/audio/ (audio.zig queue+worker, mixer.zig), native AudioDevice, audio.md
Renderer policyshared graphics/ and RHI
Shared frame-ring GPU buffergraphics/renderer/dynamic_buffer_manifest.zig + both platform/*/graphics/dynamic_buffer_types.zig adapters
Engine scene componentscene/components/<name>.zig (descriptor, authoring rows, presentation, normalization, live topology) + scene/components/builtin_components.zig catalog; keep publish/spawn policy in its owning subsystem
Engine builtin capability/storagesdk/src/builtin_component_manifest.zig + scene/world/world_components.zig; keep publish/spawn policy in its owning subsystem
API implementationplatform/native driver folders
Authoring behaviorShared plane editor/authoring/scene_mutation.zig → editor.Document / SceneDocument (architecture, ui-and-editor)
Scene transactions (plugins)sdk/src/editor_scene.zig (hi.editor.scene()) → host game_contrib → scene_mutation (Plugin API)
Package settingssdk/src/settings.zig (hi.settings) → .engine/plugin-settings/<id>.json
Post-process pass registrationsdk/src/post_process_pass.zig + hi.render().registerPostProcessPass (fixed assemble slots; do not extend pass_registry.Kind)
Host editor panels / menuseditor/contrib.zig + bindFill (docs)
Asset processingShinra plugin/pipeline + runtime reader
Product buildtyped Kaji plan/build unit

Prefer a narrow, explicit boundary over cross-layer switches. In particular, do not make shared code select platforms, expose native handles, or make the live World the editor's authoring database.

Engine extension manifests

Mechanical, compile-time obligations are centralized without introducing runtime registration or indirect calls:

  • sdk/src/builtin_component_manifest.zig owns stable builtin names, reserved authoring identities, ids, and capability flags. builtin_components.zig supplies the concrete SDK declarations and is order-checked against it; entity queries and scripting filters walk the generated capability fields.
  • scene/components/<name>.zig is the public contract for one engine-authored component: its Desc, optional authoring_rows, editor presentation/placement, document canonicalization, runtime target, and structural/picker field declarations. Component-specific owned seeding may live there too. scene/components/builtin_components.zig only maps the actor tag to that module. scene_asset.zig, editor/component_catalog.zig, editor/component_schema.zig, and scene/world/live_fields.zig are adapters/facades, not second definitions.
  • scene/world/world_components.zig owns typed store shape, capacity, reservation policy, lifecycle walks, and ownership binding. Resource-specific teardown remains explicit in scene/entity.zig; a new store without a teardown policy fails compilation.
  • scene/actor_fields.zig derives builtin actor block names from the JSON wire type. That identity also drives prefab equality/refresh and editor presence/schema lookup. scene/scene_actor_json.zig is the canonical actor writer for both scene documents and prefabs; JSON→descriptor conversion must go through the checked copyMatching path.
  • graphics/renderer/dynamic_buffer_manifest.zig owns shared frame-ring buffer membership and lifecycle. Each backend maps every logical name to a concrete buffer in dynamic_buffer_types.zig; creation/destruction is compile-time unrolled, and render code reads renderer.dynamic_buffers.<name> directly.

These manifests cover repeated identity, pairing, storage, and lifecycle work. Keep feature decisions—GPU record packing, scene spawn/materialization, pass scheduling, and publish hot paths—explicit in the subsystem that owns them. Component inspector labels/ranges belong to the component contract. This preserves compiler-visible direct calls and makes a new feature's remaining edits meaningful rather than registration ceremony.

Product Zig std (hikari_std)

Engine, game, and editor Zig modules do not import Zig's std directly (toolchain: Zig 0.16.0, pinned in 3rd-party/zig/VERSION). Use:

zig
const std = @import("hikari_std");
// then std.mem, std.Thread, std.heap, …
  • Source: src/hikari/sdk/src/std/root.zig (module name hikari_std; also hi.std).
  • Only that file may @import("std") (Zig). Today it re-exports Zig std; platform-specific heap/time/threads/etc. branch there later.
  • Exempt: build.zig and build/** (host toolchain).

Validation

Use the smallest check that proves the path changed, then a product-level check when integration moved:

  • Engine Zig unit work: from src/hikari, zig build test -Dgame-src=../games/example/src (or another game src/).
  • Entity performance changes: zig build entity-bench -Dgame-src=../games/example/src (ReleaseFast; split metrics + composition tile sweep; baselines in src/hikari/src/tools/entity_bench_baselines.md).
  • Kawa changes: its local build/examples plus the project build path.
  • Renderer policy changes: prefer src/hikari/src/graphics/ (shared). Touch Metal and D3D12 only for native encoding/sync; then run the relevant product build on each host you changed. After shared graphics: zig build check-windows -Dgame-src=<abs> (Windows/D3D12 type-check only — no link).
  • Native C / ObjC / C++ (Metal, D3D12, frontends): zig run src/hikari/tools/native_style.zig -- format|tidy|compile-db (wrappers native-style.sh / .ps1). Format is host-agnostic; clang-tidy needs the matching SDK (see below). Not a Kaji product step.
  • Product/package changes: Kaji game/editor command with the exact link mode you changed.
  • Shipping macOS matrix: build/test-build-macos.sh.
  • Windows matrix: build/test-build-windows.ps1 (same grid intent; game cells omit --project= today — see Build and packaging).

Dynamic and monolithic modes validate different ownership and loading paths. A monolithic success is not evidence that a dynamic module lifecycle change works.

Native C / ObjC / C++ style (Metal + D3D12)

The engine's native trees are a C ABI with two implementations: macOS ObjC/ARC + Metal and Windows C++20 + D3D12 (WRL::ComPtr). Format is one house style; lint overlays are per platform.

FileRole
src/hikari/.clang-formatC / C++ / ObjC / ObjC++ format (4-space, left pointers, Allman on functions, attached control braces)
src/hikari/.clang-tidyShared bug/analyzer/readability baseline. No modernize-* here — this is a handle/C ABI layer
src/hikari/src/native/macOS/.clang-tidy + .clangdMetal / AppKit / ARC (objc-*, clang-analyzer-osx.*)
src/hikari/src/native/Windows/.clang-tidy + .clangdD3D12 / Win32 (microsoft-*, nullptr/override, Agility + PIX includes)
src/hikari/src/native_frontends/{macOS,Windows}/Process frontends (ObjC++ vs C++20); both include shared/frontend_core.inl
bash
# Zig 0.16 (same helper pattern as unused_pub.zig). clang-tidy: brew install llvm@22 — unversioned `brew install llvm` is a stub on this repo's Tenkai path.
zig run src/hikari/tools/native_style.zig -- format            # all native trees
zig run src/hikari/tools/native_style.zig -- format --check
zig run src/hikari/tools/native_style.zig -- tidy              # host SDK only
zig run src/hikari/tools/native_style.zig -- tidy --platform macos
zig run src/hikari/tools/native_style.zig -- compile-db        # build/cache/native-lint/compile_commands.json
src/hikari/tools/native-style.sh format                       # finds zig, cds to repo root
powershell
src/hikari/tools/native-style.ps1 format
src/hikari/tools/native-style.ps1 tidy

clangd picks up the nearest .clangd. Warnings are advisory: product compiles already use -Wall -Wextra -Werror / /W4 /WX /analyze. Do not mass-format -i without an explicit cleanup change — the configs describe the intended style, not a guarantee that every existing file matches it.

clang-tidy on D3D12 files needs a Windows SDK (and the other way around for Metal). Format does not.

Error and allocation policy

Fail fast for unrecoverable setup invariants and one-time out-of-memory conditions. Best-effort capacity reservation may be ignored only if a later append retries and correctness remains intact. Per-frame backend allocation failures should retry next frame and be counted/throttle-logged; dropped render work must also be counted/throttle-logged.

Keep ownership explicit and avoid hidden per-frame allocations. UI, rendering, and scene frame paths retain/prewarm capacity where appropriate. Persistent World/entity memory goes through GameplayAllocator (src/hikari/src/memory/gameplay_allocator.zig) — do not bypass it with ad hoc page_allocator on spawn hot paths. That heap is game-thread only (Debug/ReleaseSafe panic on a foreign-thread call); anything another thread allocates or frees — render-command payloads (vertex buffers, meshlet topology, particle program bytes), the render command queue and its staging pool, the frame swap and surface-UI mailboxes, the material cache (shader companions are built on the render thread through Material.allocator), parallel slice worker buffers — lives on World.shared_allocator, the thread-safe parent heap. RenderComponent/RenderPrimitive are built on it, and the queue asserts every payload allocator at enqueue.

Debug leak tracking (ReleaseFast is a no-op): GameplayAllocator dumps grouped alloc stacks on World.destroy; SubsystemAllocator (Host, Platform, Dispatch, Game, Physics, Play) uses Zig DebugAllocator with 6-frame stacks in Debug. Play Stop checks the Play world + Play heap; editor/game quit checks every owned world, then Physics/Game/Dispatch/Platform, then the frontend Host heap. A full empty-world unload (unloadScene / budgeted unload) also Debug-checks transient gameplay leftovers (Gameplay(scene)). Overlap-swap (incoming scene already spawned) and additive layer unload do not — other actors still own the heap. World-lifetime structure uses World.durableAllocator() (intern, SoA, handle table, native update batch table, LOD tables, skybox path). A budgeted-unload entity snapshot must be freed before finishBudgetedUnload. HIKARI_ALLOW_LEAK=1 soft-fails subsystem leaks in Debug; Kaji --memory-leak-check --run sets HIKARI_FAIL_ON_LEAK=1 for ReleaseSafe. Per-tick World.arena is not leak-checked as a drain.

Documentation policy

Update the relevant page in this docs/ tree with architecture, build-flow, or platform-status changes. Keep source comments focused on local invariants; keep cross-system behavior here.

AGENTS.md files are for AI assistants: short package maps, hard contracts, forbidden patterns, and validation commands. They must not become a second copy of this docs tree. When behavior changes, update the matching docs/ page for humans and only adjust AGENTS.md when agent-critical paths, invariants, or build commands change.

PreviousGuidesNext Gameplay API

Documentation follows the current engine checkout.

Snapshot cc148c75Source docs/guides/development.md
On this pageRead before changingEditor syntax highlightingChange by seamEngine extension manifestsProduct Zig std (hikari_std)ValidationNative C / ObjC / C++ style (Metal + D3D12)Error and allocation policyDocumentation policy Back to top