ableton-guide — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited ableton-guide (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
You control Ableton Live by sending Python code via the execute tool. Each call is a fresh scope with these variables:
song, app, tracks, returns, master, browser, Live, MidiNoteSpecification, find_item, find_items, find_track, load_to, log, json, time
Use api() and search_api(query) to explore the Live API reference.
These are in scope every call — no imports or definitions needed.
`MidiNoteSpecification(pitch, start_time, duration, velocity)` — create MIDI note specs:
clip.add_new_notes(tuple([
MidiNoteSpecification(pitch=60, start_time=0.0, duration=0.5, velocity=100),
]))`find_item(parent, query)` — search a browser tree for the best-matching loadable item (case-insensitive, breadth-first, prefers exact matches). Returns BrowserItem or None:
find_item(browser.instruments, "Grand Piano")
find_item(browser.drums, "808") # finds "808 Core Kit" not a random 808 sample
find_item(browser.audio_effects, "Reverb")`find_items(parent, query, limit=20)` — like find_item but returns a ranked list. Use when you want to see candidates:
find_items(browser.drums, "808") # → [808 Core Kit.adg, 808 variants…, individual 808 hits…]`find_track(name)` — look up a track by name (case-insensitive). Returns Track or None:
bass = find_track("Bass")
bass.mixer_device.volume.value = 0.8`load_to(track, parent, query)` — find a browser item, select the track, and load it. Returns the BrowserItem. Raises ValueError if nothing matched:
load_to(song.tracks[0], browser.instruments, "Grand Piano")
load_to(find_track("Drums"), browser.drums, "808")execute don't carry over.find_track(name) or song.tracks (not the tracks shortcut, which is a stale snapshot).for i in range(len(song.tracks) - 1, 0, -1): song.delete_track(i)song.undo() to roll back.load_to or browser.load_item). Without it, loads silently fail.result: result = [(i, t.name) for i, t in enumerate(song.tracks)]Clean slate:
for i in range(len(song.tracks) - 1, 0, -1):
song.delete_track(i)Create a track with a clip:
song.create_midi_track(-1)
idx = len(song.tracks) - 1
song.tracks[idx].name = "Bass"
song.tracks[idx].clip_slots[0].create_clip(8.0) # 8 beats = 2 barsPlay everything:
for t in song.tracks:
t.clip_slots[0].fire()
song.start_playing()~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.