6.8 KiB
CLAUDE.md — HOT-Step CPP
Orientation map for agents. Keep this short and navigational — point at the deep docs, don't duplicate them.
What this is
A desktop app for local AI music generation — a heavily-extended superset of acestep.cpp (a C++/GGML port of ACE-Step 1.5). Caption + lyrics in → stereo 48 kHz audio out, fully local. Ships as portable releases (Windows CUDA/Vulkan/CPU, Linux, macOS Metal). GitHub: scragnog/HOT-Step-CPP.
Architecture (3 tiers)
| Tier | Stack | Location | Role |
|---|---|---|---|
| Engine | C++17 / CUDA / GGML | engine/ | Inference binaries: ace-lm, ace-synth, ace-server, ace-understand, neural-codec, mp3-codec, quantize. Pipeline: LM → DiT → VAE |
| Server | Node / TypeScript / Express / better-sqlite3 | server/src/ | Orchestrates the engine, manages songs/jobs/SQLite, serves UI. Per-feature routes/ + services/ |
| UI | React 19 / Vite / Zustand / Tailwind | ui/src/ | Browser frontend. Component folder per "studio" |
LAUNCH.bat → Node server (Express :3001)
├── serves React frontend (prebuilt ui/dist/)
├── /api/* → SQLite
└── spawns child: ace-server.exe (C++ engine) on :8085
| Service | Port |
|---|---|
| Node server | 3001 (prod) |
| Vite dev server | 3000 (dev, HMR) |
| ace-server (C++ engine) | 8085 (default, config.ts) |
Environment
- Windows 11 + PowerShell. This repo's primary dev environment is Windows. The Claude Code harness also gives you a Bash (POSIX) tool — each takes its own syntax. In PowerShell use
;not&&. - Node 18–22 LTS only. Node 24+ breaks dependencies (
enginesfield enforces<24).
Build & run rules (IMPORTANT — learned the hard way)
- C++ engine changes →
dev-rebuild.bat, NEVERengine/build.cmddirectly. The Node server auto-respawns ace-server on crash; killing it without clean shutdown causes an infinite respawn + file-lock loop.dev-rebuild.bathandles clean shutdown + rebuild — it does not relaunch; start the app again yourself withdev.bat/LAUNCH.bat.- Recompile immediately after editing any
engine/src/orengine/tools/file — don't wait to be asked.
- Recompile immediately after editing any
- NEVER
cmake --build . --clean-firstunless the GGML/CUDA layer itself changed — CUDA kernel recompilation is 20+ min. For stale.objissues, delete onlyengine/build/acestep-core.dir/andengine/build/Release/acestep-core.lib. - Don't
npm run buildduring dev. Type-check withnpx tsc --noEmit. Only build before user testing. dev.bat= dev mode (Vite :3000 HMR + Node :3001, tsx watch auto-restart).LAUNCH.bat= prod. Usedev.batfor development.
Git rules
- All work on
master. No feature branches, ever. - Never
git add -A(re-adds gitignored dirs:.agents/,checkpoints/,node_modules/, etc.). Nevergit add -fon gitignored paths. Stage explicit paths. - Push requires explicit user approval — always ask first.
- Commit to local git often (data has been lost before to uncommitted files).
- Releases: push a
vX.Y.Ztag → theReleaseworkflow builds all platforms and drafts a GitHub Release. Any pushedv*tag triggers a build — use a-CI-Testsuffix for throwaway compile checks, and don't push local feature tags matchingv*. Full process + gotchas: docs/RELEASING.md. - Use
ghCLI for GitHub ops (authenticated asscragnog).
Upstream sync (fork hooks that break silently)
The C++ engine is a patched fork of acestep.cpp. Three upstream files carry HOT-Step #include hooks that break if overwritten during a sync:
| Upstream file | Hook | If lost |
|---|---|---|
pipeline-synth-ops.cpp |
hot-step-sampler.h (replaces dit-sampler.h) |
SILENT — compiles, but all solvers/guidance/schedulers go dead |
model-store.h |
hot-step-params.h |
compile error |
dit.h |
adapter-merge.h + adapter-runtime.h |
compile error |
After any sync: run engine/verify-hooks.ps1. Full process: docs/plans/upstream-sync-workflow.md (local, gitignored).
UI / browser verification
- Don't use the built-in browser agent to visually verify UI — too slow/unreliable here. Ask the user to check; they provide screenshots/feedback. Browser agent is fine for non-visual tasks (hitting API endpoints).
Debugging — logs
App writes per-session logs to logs/ at repo root:
logs/YYYY-MM-DD_HH-MM-SS/ ← one folder per session (name-sorted = time-sorted)
├── ace_engine.log ← C++ engine output
├── node_console.log ← Node server output
└── generations/gen_<uuid>_<task>.log
Start with the newest session folder. Generation failures → matching gen_*.log first, then cross-ref ace_engine.log + node_console.log. Startup/crash → node_console.log + ace_engine.log.
Plugin system
Solvers (17), schedulers (9), guidance modes, and postprocess are hot-loadable Lua plugins in engine/plugins/ — drop a .lua in the right subdir, appears in the UI next launch, no C++ rebuild. Each plugin can declare its own UI params. Native C++ bridge via apg(); advanced plugins use post_step() for extra forward passes. Adding a solver/scheduler/guidance = write a .lua plugin (the old approach of editing dit-sampler.h is obsolete — the engine now routes through hot-step-sampler.h). Authoring guide: docs/PLUGINS.md.
Read-Y-for-X index
| For… | Read |
|---|---|
| Any maintenance task — start here (per-domain procedures, gotchas, distilled institutional knowledge) | .claude/skills/README.md — 13 fact-checked skills |
| Full feature catalogue (100+) | FEATURES.md |
| Engine internals, CLI, request JSON, generation modes | engine/docs/ARCHITECTURE.md |
| Training system (dataset→preprocess→LM/DiT training→audition; ace-train, FSQ, ggml training gotchas) | docs/TRAINING.md |
| Writing a Lua plugin | docs/PLUGINS.md |
| Build / install / releases | README.md |
| Cutting & publishing a release (agent runbook) | docs/RELEASING.md |
| Internal design/investigation docs (perf, adapters, upstream sync, feature designs) | docs/plans/ (gitignored, local-only) |
| In-app assistant behaviour/KB | server/src/data/assistant-knowledge.md |
Doc convention: committed contributor-facing docs =
README.md,FEATURES.md,docs/PLUGINS.md,engine/docs/ARCHITECTURE.md. Internal planning/investigation docs live indocs/plans/, which is gitignored (local only). This file (CLAUDE.md) is committed.