mcerqua/openvoiceui/suno-music
Claude Code and agent skill by mcerqua/openvoiceui
- community
Checking that the SKILL.md file is still in the repository.
Make AI music through OpenVoiceUI's Suno integration - full songs, 10-15s brand jingles, sound effects, extends, covers, added vocals or instrumentals, section edits, vocal stems and download links. Always via OVU tags or /api/suno. Needs SUNO_API_KEY in .env.
Install
npx vskill@latest install mcerqua/openvoiceui/suno-musicSKILL.md
Suno Music
OpenVoiceUI (OVU) wraps the Suno API (sunoapi.org) behind two voice tags and /api/suno. It submits the job, saves the finished audio in generated_music/ with its metadata (title, lyrics, Suno ids) and adds it to the music player's Generated playlist.
- Requires `SUNO_API_KEY` in the OVU `.env`; without it every
/api/sunocall returns
{"action":"error","response":"SUNO_API_KEY not configured ..."}.
- Examples use
http://localhost:5001; if you changed PORT, use that port. -H "X-Agent-Key: ${AGENT_API_KEY:-}"is needed only when the install requires login (Clerk +
CANVAS_REQUIRE_AUTH) and AGENT_API_KEY is set in .env; harmless otherwise.
- Everything is async: songs and jingles take about 45-90 s, sound effects about 20-60 s.
Rules
- Always go through OVU (the tags or
/api/suno). Never call the Suno provider directly and
never use OpenClaw's built-in music tool: only OVU saves the file in generated_music/ with metadata and a shareable URL. Anything else is paid for and invisible to the user.
- Never write into `generated_music/` yourself, never invent a filename or URL.
- Every generation costs credits (approximate: song or jingle ~12, since Suno makes two clips
and OVU keeps the first; sound effect ~2.5; the live balance comes from the provider). Never fire the same request twice.
- Do not say it is done until you see the completion notice or
statusreturnscomplete. - No real artist or band names anywhere in a request; the provider rejects them. Describe the
sound (genre, era, instruments, mood, tempo).
- Never put `[` or `]` inside a tag. The tag ends at the first
]; the request is truncated
and the rest is spoken aloud.
Which method
| Request | Method | |
|---|---|---|
| A song, during a conversation | [SUNO_GENERATE:...] | |
| A jingle, audio logo, sting, intro or on-hold greeting | [JINGLE_GENERATE:...] | |
| A sound effect (game blip, impact, ambient bed) | API action=sfx (no tag) | |
| Structured lyrics, female vocal, guaranteed instrumental, several songs, canvas page or script | API action=generate | |
| Change an existing song | API edit actions | |
| Separate vocals from music | API action=stem_separate |
Tag: [SUNO_GENERATE:...] (full song)
Options after the first | are optional. The browser submits it, shows a status banner and polls until the song is saved. On the user's next turn you get [SYSTEM: Suno just finished generating "<title>" ...]; if they want to hear it, reply with [MUSIC_PLAY:<title>]. The tag is removed from speech; say it will be ready in about a minute.
- Description mode (normal): Suno writes the lyrics and picks the title, so
title:is
ignored and the filename follows Suno's title. Style plus description is cut to 500 chars.
- Vocals default to male and the tag cannot change that; use the API with
"vocal_gender":"f". - "No vocals" is only a hint; use the API with
"instrumental":truewhen it must be instrumental. - One tag per reply. The browser tracks one job at a time and drops an identical prompt
repeated within 60 s. For several songs, use the API.
voice: sings the description as lyrics (lines separated by newlines or/) in the cloned
voice stored as voice_persona_id in the active profile (see Personas); without it, a default voice.
Tag: [JINGLE_GENERATE:...] (10-15 s brand jingle)
| Field | Values | Default | |
|---|---|---|---|
brand (required) | Name to sing, spelled as it should sound (B-M-W, Open Voice U-I) | - | |
style | A preset key, or freetext (only the first 3 words are used), or empty | random preset | |
gender | m or f | m | |
instrumental | true for an instrumental audio logo | false | |
repeat | How many times the brand is sung, 1-3 (1 is shortest) | 2 |
Presets (action=jingle_styles): rock, country, cinematic, gospel, lofi-hiphop, jazz, edm, bluegrass, synthwave, latin, reggae, gritty-blues, orchestral, punk, rnb. With no style from the user, leave it empty.
Users call this a jingle, logo jingle, audio or sonic logo, brand sting, stinger, bumper, station ID, podcast or channel intro, on-hold or IVR intro. Treat all of them as a jingle and ask only for the brand, a style (or "surprise me") and male, female or instrumental.
Clean the brand, keep the delivery. When users type how it should be sung (OOOOhhhPIN-VoIcE- UUUUUIIIIII, BEEEEM-DOUBLE-YOUUU), put the plain phonetic name in brand (OpenVoice U-I, B-M-W) and the delivery in up to three freetext style words: stretched vowels -> sustained operatic vocal; hyphenated letters -> punchy spelled-out chant; CAPS with !!! -> shouty stadium chant; lowercase with ... -> breathy intimate whisper. Anything that is not exactly a preset key is freetext, so a preset cannot be combined with extra words. If unsure, ask one short question before the paid generation.
The server builds a short prompt (<brand> <brand> <style word> vocal logo jingle, [Intro, model V5) designed to stop early. To omit the style word entirely (bare), use the API.
Length is not guaranteed. Suno often overshoots. Over 20 s, the status reply says so; check duration_seconds via action=list_jingles and offer a retry rather than presenting a long clip as a finished jingle.
Sound effects: action=sfx
Fields: prompt (required, short and literal, max 500 chars), title, loop (true for a seamless bed), tempo (BPM 1-300), key (e.g. Cm; omit for any).
- Poll `action=status` yourself until
complete: sound effects have no callback, so your
poll is what downloads the file.
- Saved to
generated_music/sfx/<file>; not in the music player oraction=list. - The
urlthatstatusreturns (/generated_music/sfx/<file>) plays directly; add
?download=1 to save it. To bundle the clip with a canvas page instead, copy it and reference /canvas-data/<file>: mkdir -p ~/.openclaw/workspace/canvas-pages/_data && cp ~/.openclaw/workspace/generated_music/sfx/coin-pickup.mp3 ~/.openclaw/workspace/canvas-pages/_data/
- Generate once and reuse the file; never regenerate per play.
Direct API
POST /api/suno with JSON containing action (reads also work as GET /api/suno?action=...). Submit returns {"action":"generating","job_id":"...","task_id":"...",...}; any failure returns {"action":"error","response":"<reason>"}.
Song: action=generate
| Field | Notes | |
|---|---|---|
prompt | Description; treated as lyrics if it contains [Verse, [Chorus, [Hook or [Bridge | |
lyrics | Explicit lyrics (custom mode, where title is used) | |
style | Genre and sound | |
title | Custom mode only | |
instrumental | default false | |
vocal_gender | m (default) or f | |
persona_id, persona_model | See Personas |
Model V5_5. Section tags like [Verse] are fine here because they are not inside a voice tag.
Jingle: {"action":"jingle","brand":"Acme Plumbing","style":"country","vocal_gender":"m","instrumental":false,"repeat":1} (also bare).
Poll: action=status
- Poll every 10-15 s until
actioniscompleteorfailed. When the provider's callback
cannot reach this server (no public domain), polling is what saves the file, so an API job you never poll may never land.
- Always pass `job_id`; without it you get an arbitrary job.
complete:title,url,duration_seconds(first reply), and aresponseto relay (for a
jingle it notes a long clip). failed: reason. not_found: wrong id or the server restarted (jobs live in memory); check action=list.
Lists and lookups
| Call | Returns | |
|---|---|---|
GET /api/suno?action=list | songs[] newest first: filename, title, url, duration_seconds, lyrics, has_word_sync | |
GET /api/suno?action=list_jingles | jingles[]: filename, brand, style_key, vocal_gender, instrumental, duration_seconds | |
GET /api/music?action=latest | track: filename, title, url, download_url (newest by file time) | |
GET /api/suno?action=credits | credits; on action:"error" the balance is unknown, say so and never guess | |
DELETE /api/suno/song/<filename> | Archives a song (renamed .deleted, never destroyed) |
generated_music/ is /app/runtime/generated_music/ in the OVU container, ~/.openclaw/workspace/generated_music/ in the agent container, and runtime/generated_music/ in a native install. generated_metadata.json there holds per-file title, kind (song or jingle), lyrics, duration_seconds, suno_id, task_id and jingle fields. Read it; do not edit it.
Delivering a song (download link)
<filename>is the exact filename.?download=1saves the file; drop it to play inline./generated_music/is public even when login is required, so this is the link to text or email.- A
http://localhost:5001/...link only works on that machine. - Latest song: the
[Latest generated song: '<title>' (file: <file>) ...]line in your
context, or GET /api/music?action=latest.
- A song by name: look it up, never guess:
```bash curl -s "http://localhost:5001/api/suno?action=list" \
`` If several match (e.g. -2` variants), ask which one or offer the newest; give one link.
- The
[Available tracks — ... Generated (N): ...]line lists titles for[MUSIC_PLAY:<title>],
not filenames.
- Never use
/music/<file>for a generated song (that is the uploaded library and returns
{"error":"Track not found"}), never emit a [CANVAS:...] download page (none exists), never paste the whole list of URLs.
Editing existing songs
Name the source with filename (preferred; OVU finds its Suno ids), or audio_id / task_id, or song_url. Each returns a job_id; poll status; the result is a new track.
| Action | Needs | Fields | |
|---|---|---|---|
extend | Suno audio id | prompt, style, title, continue_at (s), model; omit prompt and continue_at for provider defaults | |
cover | Public URL | style (enables custom mode), prompt, title, instrumental, model | |
add_vocals | Public URL, prompt | style, title, vocal_gender, negative_tags, model | |
add_instrumental | Public URL | tags or style, title, negative_tags, model | |
replace_section | Task id + audio id, prompt | start_time, end_time (s, end > start), tags, title, full_lyrics; provider window roughly 6-60 s |
This is the start of the file. Read the full SKILL.md on GitHub.
Security
- Security scanPassed, 90 of 100Pattern checks on the skill's files.
- Model reviewPassed
Quality evaluation
- Task evaluationNot runNo evaluation yet. Run one in Skill Studio.
Source
- SKILL.md in the repositoryCheckingskills/suno-music/SKILL.md
Popularity
- Repository stars
- 80
- Repository forks
- 16
- 7-day trend score
- 0
Stars and forks are for the whole GitHub repository, not this skill alone. Not refreshed yet.
Works with
Any agent vskill installs to: 56 targets in all. These 39 have a page on this site.
- Claude Code
- Cursor
- GitHub Copilot
- Windsurf
- Codex
- Gemini CLI
- Cline
- Amp
- Roo Code
- Goose
- Continue
- Kilo Code
- Junie
- Trae
- OpenHands
- Qwen Code
- AI Agent
- Tabnine Chat
- Sourcegraph Cody
- Amazon Q
- Firebase Genkit
- Sweep
- Devin
- Phind
- Mentat
- Claude Desktop
- Aider
- GPT Pilot
- Plandex
- bolt.new
- v0
- Replit Agent
- Anse
- TypingMind
- BetterChatGPT
- LibreChat
- Warp AI
- Pieces
- Fig AI
Embed badge
[](https://verified-skill.com/skills/mcerqua/openvoiceui/suno-music)