This folder is a local reference and development environment for VirtualDJ skinning, pad pages, and VDJScript. VirtualDJ does not publish comprehensive developer documentation; this repo fills that gap.
README.md — human-facing project overview
TODO.md — active operational queue for open-ended work
INDEX.yml — topic-to-file routing map
docs/README.md — index of all reference docs, source label policy, current status
docs/VirtualDJ Reference.md — Quick Decisions guide: preferred methods, rationale, examples
docs/VDJScript Verbs.md — curated API reference: canonical names, aliases, surfaces
docs/Official VDJScript Coverage Audit.md — authoritative names-only parity audit and local-test gap count
docs/Completeness Roadmap.md — ordered backlog for closing behavior, fixture, and hardware gaps
examples/Pads/README.md — pad page inventory, status labels, and maintenance checklist
tests/README.md — documentation test harnesses and reproducible fixtures
For “what should I do next?”, maintenance, documentation cleanup, or evidence-pass work, read TODO.md first. Treat TODO.md as the canonical active queue and start with the first Ready task unless the user names another task.
Context load is the dominant cost in this repo. These rules outrank thoroughness:
- Writing VDJScript? Read the summary of docs/VDJScript Grammar.md first. Its "Read this much" section is the whole language in about a dozen lines; the Contents list jumps to a section when you need detail. Grammar is the one thing lookup cannot save you on — the parser reports no syntax errors, so wrong script silently does something else. Not writing script (skin layout, XML structure, file format work)? Skip it.
- Never read the large docs end-to-end.
docs/VDJScript Verbs.md(~6,300 lines),docs/Skin SDK.md(~2,700 lines),docs/Effects Engines.md,docs/VirtualDJ Reference.md, anddocs/VDJScript Local Test Tracker.mdare section-addressed references. Read only the section a task names, or extract it with path-scopedrg/awk. - Start a "how do I do X" task with
just topic X. It aggregates, for one term, the matching verbs, effects, and skin/pad XML elements, plus the real example files that use them (grep-verified, ranked by how much of the topic each demonstrates), the topical docs, and known local-test quirks. A working example often answers the task outright, leaving only per-verb detail to look up.just topic sampler,just topic colorfx,--format=jsonfor structure. Drill in withget-verb/get-fx/get-xml-elementafterward. - Look verbs up through the tooling, not the monolith.
just get-verb <name>is the lookup — it follows aliases and suggests near matches on a miss.just find-verbs <term>when you do not know the name. OpenVDJScript Verbs.mdonly at the specific lines a search hit points to. - Record a settled verb fact with
just put-verb, not by hand-editing tables. A per-verb conclusion — status, confidence, evidence — goes into the store once (just put-verb <name> test_status=Pass confidence=local_test evidence="…"), not promoted into the tracker and topical docs by hand. The tracker is for the run narrative that does not reduce to one verb (see the Live probe section); the store is the authoritative per-verb record. A tested status without evidence failsjust check. - Effect controls come from the FX catalog, not prose tables.
just get-fx Echogives the full slider/button map with normalized defaults (spelling-tolerant:BeatGridresolves toBeat Grid,Shaderto its canonicalVisuals);just find-fx --category=video_fx,--has-button=quant,--min-sliders=6,--has-length,--format=jsonanswer the rest. Do not hand-transcribe the catalog into Markdown. - Introspect effects by name, without loading them. Every
get_effect_*helper accepts an effect name where the docs show a slot number —just vdj-query "get_effect_slider_count 'Echo'",get_effect_slider_default 'Echo' 3— so a live question about an effect needs noeffect_selectand changes no state.get_effect_title '<name>'returns'<Canonical> - Deck N'or'', which resolves spellings and probes existence in one call. - Query the store instead of reading listings.
just find-verbsfilters —--surface,--section,--tier,--status,--kind,--needs-test— and--format=jsonfor structured output. Ask for the verbs you need (just find-verbs --surface=SkinQuery --section=Sampler); do not pull a category listing and filter it yourself.just next-incomplete-verbgives the next active (non-hardware-blocked) work item,just verb-statsthe breakdown. - Planning docs are frozen.
docs/VDJScript Reference Consolidation Plan.mdanddocs/Completeness Roadmap.mdare design references, not active state. Do not refresh, reorder, or re-scope them; do not spend turns rewriting planning prose or reordering the TODO queue.TODO.mdis the only active planning state, and it changes when a task completes or the user asks. - Probe over HTTP first, fixtures second. When VirtualDJ is running with the network interface enabled (
just vdj-upto check), read values withjust vdj-queryinstead of pad readback. Pad/skin fixtures remain necessary only for surface-specific behavior (rendering, pad context, skin runtime). Batch every probe a live session can carry, and prefer dump-style sweeps over one-question rounds. - Delegate mechanical passes. Transcribing observed values into tables, promoting settled tracker rows, and lint fixes are cheap-model subagent work; keep the main context for evidence interpretation and ambiguous calls.
- Prefer
INDEX.yml,just next-task,just grep-verb-docs <name>, and path-scopedrgover repo-wide discovery; broaden only after the task route proves insufficient or contradictory. - Keep volatile coverage counts sourced from
docs/Official VDJScript Coverage Audit.md; do not repeat exact count summaries in entrypoint docs unless the checker intentionally enforces them.
Direction of travel: verb facts live in a structured record store (docs/vdjscript-verbs.json) reached only through flat just data commands — get-verb, find-verbs, put-verb, next-incomplete-verb, verb-stats (and get-fx, find-fx, fx-stats for effects). The command name is always a command and the argument is always data, so a verb called search or get can never be mistaken for a subcommand. Treat the JSON layout as private — go through the commands so storage can change (e.g. to one file per verb) without breaking your usage. Reports are queries on stdout: do not add a generator that writes a Markdown copy of store data. The store is seeded from the existing index, coverage audit, and tracker via python3 tools/verbdb.py bootstrap.
examples/Pads/ — working/reference pad page XML files plus copied built-in pad pages
examples/Skins/ — skin source trees, reference skins, and copied built-in skins
examples/Mappers/ — real working controller/keyboard mapper XML (ground truth for the mapper format)
examples/Samplerbanks/ — copied built-in sampler-bank XML (third XML format)
tests/ — documentation test harnesses, including pad XML fixtures
docs/ — Markdown documentation
When VirtualDJ is running with its network interface enabled, VDJScript can be executed and queried over plain HTTP on http://localhost/ — no pad fixture or manual readback needed. This is the preferred channel for local-test probes. Full contract, verified behavior, and gotchas: docs/HTTP Control Interface.md.
just vdj-up— reachability check; run it before planning any live-test work.just vdj-query 'get_effect_name 1'— evaluate any VDJScript query; exact result string back. Read-only, use freely for sweeps.just vdj-execute 'effect_active 1'— run an action; the body is the verb's owntrue/falseresult (not transport success —nothingreturnsfalse).- Unknown verbs return HTTP 200 with an
error:<code>body; check the body, not the status. - Execute only verbs the current task names; never
systemor file/database-touching verbs through this channel. - Recording a result has two destinations, and they hold different things. The verb store is authoritative for per-verb conclusions:
just put-verb <name> test_status=… confidence=local_test evidence="…"— one verb, one settled fact, with the build in the evidence string. The tracker holds the run narrative for a session that does not reduce to a single verb: a fixture setup, a negative result, a multi-verb probe, cross-verb interactions. A tested status in the store with no evidence now failsjust check, so record the evidence at the same time as the status, not later. Note the channel (HTTP vs pad) in the evidence, since some behavior is surface-specific.
- VirtualDJ skins are XML. The scripting language inside attributes is VDJScript.
action=""attributes take VDJScript actions.query=""takes a boolean/value expression.&chains actions in XML attributes and must be written&inside XML.- Backtick-wrapped expressions (
`verb`) evaluate and return a value in string/color contexts. - Working/reference pad pages live in
examples/Pads/*.xml; copied built-in app-bundle pages live inexamples/Pads/Built-In/; documentation test harnesses live undertests/. Seeexamples/Pads/README.mdbefore choosing a reference page. Skins live inexamples/Skins/*/; copied built-in app-bundle skins live inexamples/Skins/Built-In/. - The pad-page container format is specified in
docs/Pad Page XML.md; skin waveforms indocs/Skin Waveforms.md; the mapper format indocs/Mapper XML.mdwith real mappers inexamples/Mappers/Local/.just inventoryrefreshes the element-coverage datadocs/skin-xml-inventory.json; query it withjust get-xml-element <name>/just find-xml-elements --undocumented. examples/Skins/GraveRaver/src/is intentionally minimal and demonstrates the build system only. Do not use it as a polished skin reference.- The official VDJScript appendix coverage and local-test gap are tracked in
docs/Official VDJScript Coverage Audit.md. - docs/Evidence Standards.md governs every claim in this repo — read it before recording a finding. Three tiers: only direct observation of the running app (network protocol, HTTP interface, live pad tests, agent driving the window) proves that something works; forums, unbacked binary analysis, and official example files are leads; everything else is not recorded. Existence, kind, and behavior are separate claims. A channel's own return value is not a result. The binary can disprove a name even though it cannot prove behavior.
- Source labels (
Official,Official forum,Community,Published skin,Built-in skin,Published pad page,Built-in pad page,Local test,Inference) appear throughout the reference docs; Evidence Standards maps each onto its tier. - Run
python3 tools/check_reference_status.pyafter changing coverage counts, fixture inventories, or local reference links.
- Slot FX:
effect_select <slot> 'Name',effect_slider <slot> <param> <value>,effect_active <slot>— not name-based toggling. - ColorFX:
filter_selectcolorfx 'Name'+filterfor the main deck filter knob.effect_colorfx <1-4>+effect_colorsliderfor extra dedicated controls. - Sampler (page-aware):
sampler_pad <n>,sampler_color <n> 'auto'; comparesampler_pad_pageto text ranges like"9 to 16"and use absolutesampler_loaded <slot>guards for empty checks (sampler_loaded 16for page 2 pad 8), sincesampler_loaded <n> 'auto'tested unreliable. - Sampler (fixed slot):
sampler_play <n>,get_sample_name <n>,get_sample_color <n>. - Panels:
<panel visibility="...">for query-driven;name=""+skin_panelgroupfor persistent manual switching. - Dynamic text color: one
<text color="action">, not per-state color attributes. - Dynamic border color: not supported (CTO confirmed). Use fill or background instead.
- Time mode:
display_time 'remain,elapsed'+get_time, not custom skin vars. - Computed arguments: transport-style verbs (
loop,beatjump,phrase_sync) ignore backtick-computed arguments even when the literal works — branch to literals (var_equal '$n' 16 ? loop 16 : loop 32) or chain params (get_var '$src' & param_multiply 2 & set '$dst');setdoes accept backticks. Tested rules:docs/VirtualDJ Reference.md§Tested Grammar Rules. - beatjump: argument must be signed (
beatjump +4; barebeatjump 4is a no-op).
| File | Status | Demonstrates |
|---|---|---|
| examples/Pads/Reference - Slot FX.xml | Canonical | Slot-based audio FX pads |
| examples/Pads/Reference - ColorFX.xml | Canonical | Filter + ColorFX selection |
| examples/Pads/SAMPLER READ ONLY.xml | Canonical | Confirmed read-only multi-page sampler with absolute empty-slot guards |
| examples/Pads/Built-In/README.md | Built-in | Copied VirtualDJ app-bundle pad pages; semi-official executable examples |
| examples/Skins/Built-In/README.md | Built-in | Copied VirtualDJ app-bundle skins; semi-official executable examples |
| examples/Skins/ModularSkeleton/build/skin.xml | Unofficial (project-authored) | Minimal modular skin scaffold |
| examples/Skins/GraveRaver/src/skin.xml | Unofficial (project-authored) | Minimal XInclude build-system demo, not a skin design reference |
| examples/Pads/Quarantine/Reference - Page Aware Sampler.xml | Quarantined (personal, superseded) | Page-aware sampler labels, colors, actions — see examples/Pads/README.md before citing |
| examples/Pads/Quarantine/COLOR FX.xml | Quarantined (personal) | ColorFX selection with stems context — not the canonical pattern, use Reference - ColorFX.xml instead |
Prefer Canonical and Built-in rows for copy/paste patterns and verb evidence. Quarantined rows are real personal working files, kept only as usage examples — see examples/Pads/README.md and examples/Mappers/README.md for the full provenance tables and why quarantined mapper files should never be cited as verb evidence.
| Path | Content |
|---|---|
~/Library/Application Support/VirtualDJ/Pads/ |
Installed pad pages |
~/Library/Application Support/VirtualDJ/Skins/ |
Installed skins |
~/Library/Application Support/VirtualDJ/Mappers/ |
Controller/keyboard mappings |
~/Library/Application Support/VirtualDJ/database.xml |
Main track database |
See docs/Application Internals.md for the full path map, database structure, and stem sidecar layout.