muse is a local, agent-first CLI that turns a music prompt into an absolute path to a generated audio file, using ACE-Step 1.5 running persistently on your Mac.
muse generate "dark dreamy ambient instrumental" --duration 30 --jsonThe full product spec is in muselang.md (it uses the working name music; the shipped name is muse, and MUSIC_* env vars are MUSE_*).
Phases 1–2 of the spec are built: generate, serve, stop, status and version, JSON output, stable error and exit codes, starting the server automatically, and a mock backend. Presets, history and doctor come next.
-
Install ACE-Step 1.5 (needs roughly 10+ GB of free disk for weights and its Python environment):
git clone https://github.com/ace-step/ACE-Step-1.5 ~/Developer/ACE-Step-1.5 cd ~/Developer/ACE-Step-1.5 && uv sync --frozen
muse starts the server itself. It runs
uv run --frozen acestep-apiwith the MLX backend on 127.0.0.1:8001 and loads the models at startup. It does not usestart_api_server_macos.sh, which stops to ask about updates. The first start downloads about 10 GB of models. The log is at~/.local/share/muse/logs/server.log. -
Build muse:
make build # ./bin/muse make test
muse serve --json # start ACE-Step and wait for models (optional)
muse status --json
muse generate "nostalgic analog synth, warm tape texture" --duration 30 --bpm 78
muse stop # stops only a server muse started
muse generate "calm piano" --count 3 --output-dir ./music --json
TRACK=$(muse generate "soft ambient pads" --quiet)
muse generate "x" --dry-run --json # resolve and validate only
MUSE_BACKEND=mock muse generate "test" # sine-tone WAVs, no ACE-Step needed- JSON goes to stdout; progress goes to stderr.
- Tracks are instrumental by default. Passing
--lyricsor--lyrics-fileturns vocals on. - Existing files are never overwritten unless you pass
--overwrite. - Exit codes: 0 ok, 2 invalid args, 3 config, 4 backend unavailable, 5 generation failed, 6 timeout, 7 output, 9 incompatible backend, 10 interrupted.
Presets keep each brand's sound in one place, so agents don't have to repeat prompt wording. Copy presets/example.yaml to the path shown by muse presets path (default ~/.config/muse/presets.yaml):
muse presets list
muse generate --preset tumble --count 5 --json
muse generate --preset tumble "rainy night street, slightly darker" # adds to the preset prompt
muse generate --preset tumble --duration 45 # flags override preset valuesPrecedence, lowest first: config defaults, then the preset, then command-line flags. Unknown keys in the presets file are rejected. Run muse presets validate after editing it.
~/.config/muse/config.yaml (override with MUSE_CONFIG). Every key is optional:
backend:
type: acestep # or mock
url: http://127.0.0.1:8001
api_key: ""
acestep:
install_dir: ~/Developer/ACE-Step-1.5
model: acestep-v15-turbo
lm_model: acestep-5Hz-lm-1.7B
server:
auto_start: true # generate starts ACE-Step when nothing is listening
startup_timeout: 180s
generation_timeout: 15m
output:
directory: ~/.local/share/muse/output
format: wav
defaults:
duration: 30
instrumental: true
count: 1
presets:
file: ~/.config/muse/presets.yamlEnvironment overrides: MUSE_BACKEND, MUSE_SERVER_URL, MUSE_API_KEY, MUSE_OUTPUT_DIR, MUSE_DATA_DIR, MUSE_ACESTEP_DIR, MUSE_PRESETS_FILE, MUSE_JSON, MUSE_DEBUG.
The ACE-Step code is MIT licensed. Model checkpoints and generated output have their own terms, so check the current ACE-Step model licence before using generated music commercially.