Worked examples
Real shell scripts an AI agent (or you) can run to drive Signals & Sorcery. Each example is self-contained — copy/paste and go.
1. Compose a chill lo-fi beat
The simplest path: one compose_scene call.
#!/bin/bash
set -e
sas compose_scene \
--description "chill lo-fi hip hop beat at 85 bpm, A minor" \
--scene-name "Verse" \
--json '{
"tracks": [
{"name": "Bass", "role": "bass", "prompt": "deep, slow, jazz-inflected"},
{"name": "Drums", "role": "drums", "prompt": "laid-back, swung 16ths"},
{"name": "Keys", "role": "chords","prompt": "sparse jazzy Rhodes"},
{"name": "Pad", "role": "pad", "prompt": "soft, wide, background"}
]
}' --pretty
sas play_scene --scene-name "Verse"
2. Build a verse + chorus + transition
Compose two scenes, then a transition that bridges them.
#!/bin/bash
set -e
# Verse
sas compose_scene \
--description "mellow verse groove" \
--scene-name "Verse" \
--json '{"tracks":[
{"name":"Bass","role":"bass","prompt":"sub bass, sparse"},
{"name":"Drums","role":"drums","prompt":"minimal kick+hat"},
{"name":"Keys","role":"chords","prompt":"ambient pad chords"}
]}'
# Chorus — energetic, same key
sas compose_scene \
--description "energetic chorus, same key, bigger sound" \
--scene-name "Chorus" \
--json '{"tracks":[
{"name":"Bass","role":"bass","prompt":"driving moving line"},
{"name":"Drums","role":"drums","prompt":"full kit, punchy"},
{"name":"Keys","role":"chords","prompt":"piano stabs"},
{"name":"Lead","role":"lead","prompt":"catchy hook melody"}
]}'
# Transition
sas create_transition --from-scene "Verse" --to-scene "Chorus" --bars 2
# Play them in order: verse → transition → chorus
sas scene_activate --scene-id Verse
sas dsl_play
sleep 16 # let verse breathe
sas scene_activate --scene-id Chorus
sas dsl_play
3. Add one instrument to the current scene
Common iterative workflow — the agent doesn't need to rebuild the whole scene, just add one part.
sas add_instrument \
--name "Sub Bass" \
--role "bass" \
--prompt "thick sub, A minor, follow the root notes" \
--bars 8
4. Apply reverb to everything
Batch FX across every track in the active scene.
sas set_scene_fx \
--category reverb \
--enabled \
--preset 3 \
--dry-wet 0.35
If some tracks fail, set_scene_fx returns success: true with a failed array listing which tracks errored — the agent can then retry those individually with dsl_set_track_fx.
5. Export a scene as WAV
Render the scene offline and save to a user-specified path.
sas export_audio \
--output "~/Desktop/my-beat.wav" \
--scene-name "Verse"
# With overwrite
sas export_audio \
--output "~/Desktop/my-beat.wav" \
--overwrite
Path tilde is expanded; .wav is auto-appended if missing.
6. Search & use a sample from the library
# Find a breakbeat at 136 BPM in A minor
MATCH=$(sas search_samples \
--query "breakbeat" \
--bpm 136 \
--key "A minor" \
--limit 1 \
| jq -r '.changes.samples[0].id // empty')
if [ -n "$MATCH" ]; then
# Drop it into the active scene
sas add_sample_track --sample-id "$MATCH"
else
echo "No matching sample found — importing from disk"
sas import_samples --paths "/tmp/amen.wav"
fi
7. Stream events while an agent works
Watch what the agent is doing in real time from another terminal.
# Terminal A (an agent is running some workflow)
sas compose_scene --scene-name "Verse" --description "lo-fi" --json '{...}'
# Terminal B (human watching)
sas events stream | jq -r '
select(.event == "domainEvent")
| .data
| "\(.type): \(.payload | tostring)"
'
Typical output:
scene:created: {"sceneId":"abc","name":"Verse"}
track:created: {"sceneId":"abc","trackId":"t1","displayName":"Bass","role":"bass","kind":"synth"}
track:midi-written: {"trackId":"t1","noteCount":16}
track:created: {"sceneId":"abc","trackId":"t2","displayName":"Drums","role":"drums","kind":"synth"}
track:midi-written: {"trackId":"t2","noteCount":32}
...
8. Idempotent retry on a flaky call
KEY="compose-$(date +%s)"
for attempt in 1 2 3; do
if sas compose_scene \
--idempotency-key "$KEY" \
--description "lo-fi" \
--scene-name "Verse" \
--json '{"tracks":[...]}' 2>/dev/null; then
break
fi
echo "attempt $attempt failed, retrying..."
sleep 2
done
Same idempotency-key means the first successful response is cached (60s, per-project) — subsequent attempts during that window return the cached success without re-executing.
9. Discover a deferred tool and use it
# The agent wants to export, but export_audio isn't in its default tool list.
sas tool_search --query "export wav" --limit 3
# Top match: { name: "export_audio", ... }
# Read its full help to understand parameters:
sas help export_audio
# Now call it:
sas export_audio --output ~/Desktop/x.wav
10. Full compose → render-for-performance pipeline
#!/bin/bash
set -e
# 1. Create the scene
sas compose_scene \
--description "dark trap banger" \
--scene-name "Drop" \
--json '{"tracks":[
{"name":"808","role":"bass","prompt":"deep dark 808 with slides"},
{"name":"Hats","role":"drums","prompt":"fast triplet hats"},
{"name":"Kick","role":"drums","prompt":"trap kick pattern"},
{"name":"Lead","role":"lead","prompt":"ominous brass stabs"}
]}'
# 2. Tweak the mix
sas dsl_set_track_fx --track "808" --category compressor --enabled --preset 4 --dry-wet 0.6
sas set_scene_fx --category reverb --enabled --preset 2 --dry-wet 0.2
# 3. Send to main output
sas render_to_performance --scene-name "Drop"
# 4. Optionally export
sas export_audio --output "~/Desktop/drop.wav" --scene-name "Drop"
That's a multi-step composition → mix → perform → archive pipeline. Every line is one sas call. An agent would write this same script when asked to "make a trap drop and send it to the main speakers, then save it."