Skip to content
Back to skills

Sound Effect

ASecurity

Make sound effects (swings, hits, whooshes, reloads, UI): three versions to pick from, then wire them.

  • 77 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added October 16, 2026
ai-agentsgoshellnode

Works with

  • claude code
  • cursor
  • cli
  • mcp

Security analysis

A100/100

Pro scans all 2 files and shows the line behind each finding

Scanned October 16, 2026

npx -y skills add SummerEngine/summer --skill sound-effect --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Sound Effect?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Sound Effect
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/summerengine-sound-effect/badge)](https://www.skillsdirectory.com/skills/summerengine-sound-effect)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: sound-effect
description: "Make sound effects (swings, hits, whooshes, reloads, UI): three versions to pick from, then wire them."
license: MIT
compatibility: [Cursor, Claude Code, Windsurf, Codex]
category: audio
user-invocable: true
allowed-tools: Read Grep Glob Write Edit summer_assets_generate_sfx_choices summer_assets_choices summer_assets_generate_audio summer_assets_search summer_import_from_url summer_import_asset_by_id summer_add_node summer_set_prop summer_instantiate_scene summer_inspect_node summer_get_scene_tree summer_call
paths: ["audio/sfx/**", "scripts/**", "**/*.tscn"]
---

# /sound-effect — Make a Sound Effect and Wire It

> **IMPORTANT — the first sound effect in a chat:** before you generate it, ask the person one short question:
>
> > Do you want me to create three versions with three different models, and show them to you in a page where you pick?
>
> Say why in one plain line: the best model changes a lot from one sound to the next, so picking by ear gives a better result.
>
> - **Yes** → `assets.generate_sfx_choices`, tell them where to listen (their Studio tab opens the page, else `reviewUrl`), then `assets.choices` until they decide. Import the approved clips and wire them. The model they approve becomes their default.
> - **No** → `assets.generate_audio` with `capability: "sound_effects"` and **no** `modelId` (it uses their approved default, else ElevenLabs).
>
> Ask once per chat. After they answer, do not ask again in the same chat; follow their answer for the rest of it.

## When to use

- One-shots: swing, clash, scrape, hit, punch, impact, whoosh, pickup, jump, land, door, UI click.
- Timed sequences tied to an animation: reload, attack combo, door unlock.
- Short loops (hum, servo, energy field) up to a few seconds.

Not for: music or stingers (`music-track`), long location ambience (`ambient-bed`), voice (`voice-line`), the SFX vocabulary of the game (`audio-direction`).

## Steps

### 1. Read the audio bible

Read `.summer/audio-bible.md` if it exists and map the request to one of its SFX classes; obey its character and DON'Ts. If it is missing, offer `/audio-direction` or go on with sensible defaults.

### 2. Reuse before you generate

Generation costs credits (`dryRun: true` on the generate call shows how many). `assets.search({ query: "<subject>", assetType: "audio", scope: "all" })`; if a clip fits, ask whether to use it.

### 3. Write the prompt

Describe the physical event, not a mood. The shape that tested well:

```
Foley one-shot: <physical event with materials>, <transient + tail described>, close-mic, dry, no reverb, no music, no voices.
```

- Sword clash: `Foley one-shot: two steel longswords strike edge to edge, bright sharp metallic impact, short ringing tail that dies in half a second, close-mic, dry, no reverb, no music, no voices.`
- Punch: `Foley one-shot: a bare fist hits a heavy leather bag, deep thud with a slap on top, no tail, close-mic, dry, no reverb, no music, no voices.`
- Boulder drop: `Foley one-shot: a large boulder drops onto packed dirt, heavy low thump with a short rumble and a few small stones settling, close-mic, dry, no music, no voices.`

**Whooshes and swings:** say `air movement only, no metal ring, no impact`, or the model adds a clang.

**Timed sequences:** give the exact total length and the time of each event, and set `durationSeconds` to that length:

```
Foley sequence, exactly 2 seconds, three distinct mechanical sounds: at 0.2 s the empty magazine is released and pulled out with a metal click; at 1.0 s a full magazine is slammed in with a solid clack; at 1.6 s the charging handle is pulled back and released with a sharp metallic snap. Close-mic, dry, no gunshot, no music.
```

**Loops:** write `seamless loop` in the text and pass `loop: true`. Only ElevenLabs SFX v2 makes loops: use `assets.generate_audio` with `modelId: "eleven_text_to_sound_v2"`, or include it in a choice set.

Avoid: vibe words (`epic`, `cool`, `realistic`), several unrelated events in one prompt (split them, unless it is a timed sequence), and no length.

### 4. Length

- One-shots: 0.5-2 s.
- Animation-synced sounds (reloads, attacks): `durationSeconds` = the animation length, with the event times written in the prompt.
- Minimums: Stable Audio 3 SFX >= 1 s, Sonilo SFX 1.1 >= 0.5 s, ElevenLabs SFX v2 0.5-30 s. When a choice set includes Stable Audio 3, use at least 1 s and let the player use the front of the clip.

### 5. Pick the models

| Model id | Name | Use it for |
|---|---|---|
| `eleven_text_to_sound_v2` | ElevenLabs SFX v2 | Strong default on most sounds; the only one with seamless loops |
| `sonilo-sfx-1.1` | Sonilo SFX 1.1 | Strong default on most sounds |
| `stable-audio-3-sfx` | Stable Audio 3 SFX | Sometimes the best on fast movement (swings, whooshes); less consistent |

A choice set makes all three by default. To compare only two, pass `models`: ElevenLabs + Sonilo is the strong pair; include Stable Audio 3 for movement sounds.

### 6. Generate

Show the prompt and the length before you call; every version is a billed generation.

**Choice set (the person said yes):**

```
assets.generate_sfx_choices({ text: "<prompt>", durationSeconds: 1.0 })
```

The answer has `choiceSetId`, `reviewUrl`, the `clips` and `studioTabOpened`. The page opens in their open Summer Studio tab; if `studioTabOpened` is false, give them `reviewUrl`. Do not pick for them. Then:

```
assets.choices({ choiceSetId: "<id>", waitSeconds: 50 })
```

Call it again while `status` is `pending`. When it is `decided`, each clip with `approved: true` has `audioUrl`, `assetId` and the person's `note`. If they approved none, ask what to change and make a new set.

**One version (the person said no, or later sounds after a decided set):**

```
assets.generate_audio({ capability: "sound_effects", text: "<prompt>", durationSeconds: 1.0 })
```

Leave out `modelId` so their approved default runs. The description goes in `text`, not `prompt` (without `text` the call is refused: `text_required`). The answer's `asset` has `assetId`, `fileUrl` and `durationSeconds`.

No Summer project (an asset-only request, or the engine is not installed or not running): stop here. The clips are in the person's Summer library; give them the `audioUrl` of each approved version and skip steps 7 and 8.

### 7. Import

```
summer_import_from_url(url: "<audioUrl>", path: "res://audio/sfx/sword_clash_01.<ext>")
```

or `summer_import_asset_by_id(assetId: "<assetId>", path: "res://audio/sfx/sword_clash_01.<ext>")`. Keep the extension of the file you got (the end of `audioUrl` or `fileUrl`). When the person approved several versions, import each one (`_01`, `_02`, …) and play a random one per event for variety.

One-shots keep loop OFF in the Import dock; looping a one-shot clicks. For a loop: WAV uses Edit > Loop Mode = Forward; OGG/MP3 use Loop = on.

### 8. Wire

| Node | Use for |
|---|---|
| `AudioStreamPlayer` | UI and non-positional sounds |
| `AudioStreamPlayer2D` | 2D positional |
| `AudioStreamPlayer3D` | 3D positional (weapon swing in the world, footstep) |

One script adds the player with its settings; `scenePath` is the exact scene to change:

```
summer_run_script(scenePath="res://main.tscn", source="""
func run(ctx):
    ctx.add_node("AudioStreamPlayer3D", "SwingSFX", ctx.find("Player"), {
        "stream": load("res://audio/sfx/sword_swing_01.wav"),
        "bus": "SFX",
        "max_distance": 25.0,
    })
    ctx.save_scene()
""")
```

The bus must match the bible (`SFX`, `UI`, `Ambient`, …); the default bus is `Master`. If the bus does not exist, run `/audio-direction`.

Fire animation-synced sounds from the animation's Call Method Track (`play()`), not from `_process`.

For a sound that must outlive its emitter (a death blow), spawn a self-freeing player at runtime:

```gdscript
# scripts/audio/SfxOneShot.gd
extends AudioStreamPlayer3D

func _ready() -> void:
	finished.connect(queue_free)
	play()
```

Save it as a `.tscn` and instantiate it per event in GDScript (`preload(...).instantiate()` + `add_child`).

### 9. Check

`summer_inspect_node(path="Player/SwingSFX")`: verify `stream`, `bus`, `volume_db`. Too quiet: raise `volume_db` (+3 to +9, never past +12), else regenerate with a heavier description. Too long: `stop()` on a timer.

## Without Summer Engine

In a session without Summer Engine tools (the assets profile; the `summer-assets` skill has the whole loop), do steps 1-6 and skip steps 7-9 (import, wiring, scene check). With `assets.generate_sfx_choices`, the person picks in the page; then save each approved clip where the person asked with `assets.get` and `out` (the `summer-assets` skill says how), and tell them the path and format.

## Fallback (no MCP)

Print the prompt, the length and the target path (`res://audio/sfx/<name>.wav`), and tell the person to make it in Summer Studio, then import it.

## See also

- `audio-direction` — the SFX vocabulary this skill obeys
- `ambient-bed` — long looping textures
- `music-track` — music
- `voice-line` — speech
- `summer_docs_read` id `reference/mcp-tools-reference`

<!-- shell-commands: generated from the operation catalog by npm run generate:registry; do not edit by hand -->
## From a shell

No Summer MCP tools in this session? Run each one as a command; when `summer --version` is missing or below 4.0, use `npx -y summer-engine@latest` in place of `summer`. Fields are flags in kebab-case (`--scene-path res://main.tscn`) or one `--input '<json>'`, and `summer ops describe <op>` prints the exact input. The `summer-cli` skill has the rest.

| In this skill | Command |
|---|---|
| `assets.choices`, `summer_assets_choices` | `summer assets choices` |
| `assets.generate_audio`, `summer_assets_generate_audio` | `summer assets generate-audio` |
| `assets.generate_sfx_choices`, `summer_assets_generate_sfx_choices` | `summer assets generate-sfx-choices` |
| `assets.get` | `summer assets get` |
| `assets.search`, `summer_assets_search` | `summer assets search` |
| `summer_docs_read` | `summer docs read` |
| `summer_add_node` | `summer engine add-node` |
| `summer_get_scene_tree` | `summer engine get-scene-tree` |
| `summer_import_asset_by_id` | `summer engine import-asset-by-id` |
| `summer_import_from_url` | `summer engine import-from-url` |
| `summer_inspect_node` | `summer engine inspect-node` |
| `summer_instantiate_scene` | `summer engine instantiate-scene` |
| `summer_run_script` | `summer engine run-script` |
| `summer_set_prop` | `summer engine set-prop` |
<!-- /shell-commands -->

Files in this skill

  • SKILL.md10.3 KB
  • resource.yaml910 B

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.