Spaces:
Running on Zero
AGENTS.md
Tool-agnostic agent guidance for the ACE Music Studio repo. If you're driving Claude Code, Cursor, Aider, Codex, or anything else with file-edit + shell access, start here.
This file is the authoritative project rulebook. CLAUDE.md is Claude-specific extensions; SKILLS.md is workflow rules. README.md is the public-facing project intro β different audience.
TL;DR β the five rules
- Mayank Gupta is sole author on every commit. No agent co-author trailers. No "generated withβ¦" footers. No
--author=flag. Strip any tool-suggested attribution. - Backend = ACE-Step 1.5 XL SFT, not ComfyUI. Don't add a ComfyUI dependency under any guise.
- One pipeline instance for all modes. Generate / Cover / Extend / Edit call different entry points on the same pipeline object. Don't instantiate per-mode β it doubles memory and breaks LoRA state.
- Don't pin
spacesinrequirements.txt. HF Spaces' ZeroGPU build injects its own version. A pin causes pip-resolve failure. - Locally is the source of truth. All changes restart
python app.pyand verify on http://127.0.0.1:7860 BEFORE pushing to HF. The Space rebuild is ~5β10 min; iterate locally.
If you can't satisfy these without changing architectural shape, ask the user before proceeding.
Project shape
Single-process Gradio 5.50 app, flat top-level Python layout.
app.py Gradio Blocks entry + bootstrap + event handlers
backend.py AceMusicBackend; @spaces.GPU; duration_for; generate_with_retry
modes.py call_generate / call_cover / call_extend / call_edit (pure handlers)
models.py auto_device, MODEL_CONFIGS, vram_limit_for, HF symlink helper
lora.py safetensors header sniff + applied_lora context manager
lyrics.py Qwen 2.5 7B inference (MLX on Mac, transformers on CUDA)
stems.py Demucs htdemucs_ft stem separation wrapper
postprocess.py loudness normalisation + fade in/out
ui.py Five per-tab builders
theme.py Soft Dark Restraint palette + minimal CSS
tooltips.py Centralised info= strings β single source of truth
tests/ L1+L2 tests + GPU-deselected smoke
docs/superpowers/ spec + plan + brainstorm artifacts
Same code path locally (MPS / CUDA) and on HF Spaces. The only branching is whether _bootstrap() does the cache-mirror dance (Spaces) or just the symlink step (local).
Locked architecture decisions
These came out of brainstorming + spec design. Do not relitigate.
| Decision | Why | Code reference |
|---|---|---|
One AceMusicBackend instance, lazy init |
Avoids ~60 s pipeline rebuild per request; LoRA revert is cleaner | backend.get_backend |
Mode dispatch = separate call_* functions |
Clean handler boundaries; easy to test with mocked pipe | modes.py |
MPS vram_limit = None |
torch.mps has no mem_get_info; any VRAM gate raises AttributeError otherwise |
models.vram_limit_for |
PYTORCH_ENABLE_MPS_FALLBACK=1 set at app import |
A few MPS-unsupported ops crash mid-pipeline without it | app.py top-of-file |
HF cache β ./models/<repo>/ symlink at boot |
ACE-Step's loader looks at local paths, NOT the HF cache snapshot layout | app._bootstrap |
| MLX path for Qwen on Mac | mlx-lm is 3-4x faster than transformers on Apple Silicon for text inference | lyrics.py |
| Stacked LoRA with safetensors sniff | 4 bundled presets + arbitrary uploads; header check avoids corrupt-file crashes | lora.py |
Commit rules
- Conventional Commits:
<type>(<scope>): <subject>- types:
feat,fix,chore,docs,test,refactor,ci,perf
- types:
- Subject is imperative, lowercase, no trailing period.
- Body explains why when not obvious. Reference plan task IDs (Task 7, Task A, etc.) when the change implements a specific plan step.
- Frequent small commits; one logical change per commit.
- No agent attribution in commit message or body. See rule 1.
- Don't
git push --forcetomainunless the user explicitly says so.
Verification rules
- Tests must pass before committing.
python -m pytest tests/ -qfrom the project root. - Ruff must be clean.
ruff check . && ruff format --check . - The local app must boot.
python app.pyβ http://127.0.0.1:7860 reachable, no import error in/tmp/ace-music-studio.log. - For UI changes: open the URL in a browser (or Playwright eval) and verify the change is rendered. Don't trust a clean test run + clean ruff as proof that the UI works.
- For deployment changes: push to HF Space, watch the build, verify the runtime stage transitions to
RUNNINGbefore claiming success.
If a change requires breaking these rules, write the reason in the commit body.
Testing conventions
- TDD per the plan. Failing test first, then implementation.
- L1 + L2 in CI (no GPU). The mode handlers are tested with a mocked pipeline. We do NOT mock ACE-Step internals.
- L3 GPU smoke is opt-in (
pytest -m gpu). Lives intests/test_smoke_gpu.py. Loads the real pipeline (~32 GB cache hit on a warm machine). - L4 HF Space smoke is manual. Push, wait, click each tab, verify audio renders.
pyproject.toml has addopts = -m 'not gpu' so the default pytest invocation skips GPU. Add the marker before any test that touches ACE-Step weights.
Out of scope (v1 cap β don't add without asking)
Per spec Β§13. If you find yourself "while I'm here"-ing into one of them, stop.
- Multi-prompt batch queue
- Persistent generation history
- User accounts
- Telemetry dashboard
- Voice cloning (RVC)
- LoRA training in-app
- ControlNet-style conditioning
- Spectrogram visualization
- Multi-language UI strings
- Watermarking output audio
- Browser audio editing
- Multi-tenant rate limiting
- DAW export
If a feature you're adding requires one of these as a sub-step, ask the user before proceeding.
When you're not sure
- Read
docs/superpowers/specs/2026-05-18-ace-music-studio-design.mdβ that's the architectural source of truth. - Read
docs/superpowers/plans/2026-05-18-ace-music-studio.mdβ the task-by-task breakdown. - Read
SKILLS.mdβ process rules, debugging patterns, deployment workflow. git log --onelineβ every non-obvious decision has a fix-commit explaining the reasoning.- Ask the user. A clarifying question costs the user ten seconds. A wrong implementation costs everyone an hour.