Skip to content

About

Unofficial VirtualDJ documentation for agents and humans

Resources

Stars

2 stars

Watchers

0 watching

Forks

Repository files navigation

VirtualDJ API Reference

Community-maintained reference for VirtualDJ skinning, pad pages, and VDJScript. VirtualDJ does not publish a comprehensive developer reference; this repo fills that gap.

What is here

  • docs/ — Markdown documentation: VDJScript verb reference, skin SDK, waveform elements, pad-page schema, effects, options, filter syntax, mapper format, application internals
  • examples/Pads/ — focused pad page XML examples for ColorFX, samplers, cues, transport, reference patterns, and copied built-in pad pages; see examples/Pads/README.md
  • examples/Skins/ — skin examples, copied built-in skins, and build-system demos; GraveRaver is intentionally minimal and only demonstrates the XInclude workflow
  • examples/Mappers/ — real working controller/keyboard mapper XML copied from a local install; ground truth for the mapper format
  • examples/Samplerbanks/ — sampler-bank XML copied from the app bundle (a third XML format alongside skins and pads)
  • examples/VideoSkins/ — built-in video skins (broadcast, karaoke, live) copied from the app bundle; same <skin> format as deck skins, rendered onto the video output
  • tests/ — reproducible documentation test harnesses, pad-page XML fixtures, and the extracted data artifacts: verb-table.json (the authoritative verb set), action-contracts.json (per-verb implementation contract), verb-return-types.json (observed types and boolean truth), verb-existence-sweep.json, action-catalog.json (816 vendor descriptions), attested-tails.json (argument tails and shapes Atomix wrote), binary-vocabularies.json (argument enumerations as groups), vdjscript-corpus.json (vendor snippets from every mined source) and verb-arg-forms.json (probe results), plus the plugin-introspection*.json captures from the native channel
  • tools/ — extractors, sweeps, linters and the just query API; every artifact is regenerable and gated by just check

Setup

just install        # once per clone: creates .venv (uv) and installs requirements.txt
just doctor         # environment health: python, packages, uv, VirtualDJ, live channel
just check          # everything gated

just install needs uv (brew install uv); it pins the interpreter from .python-version and installs requirements.txt. Every recipe then runs .venv/bin/python3, falling back to the system python3 when no venv exists, so a fresh clone still answers a lookup question without any setup at all.

Run just install again after a python upgrade moves the interpreter out from under the venv. just doctor is the brew doctor of this repo and the first thing to run when something behaves oddly: it names the interpreter in use, whether it can import what the extraction tools need, which VirtualDJ is installed against the builds the artifacts are anchored to, and whether the live probe channel answers. Only the python section can fail — the extraction tools read the VirtualDJ Mach-O binary through numpy, and the failure when it is missing is quiet rather than loud.

Connect an AI assistant through MCP

The MCP server exposes reference lookups, grammar guidance, and linting to an assistant without loading the whole documentation set. It runs locally over STDIO; keep this checkout available because the server reads its tools and reference data. See MCP Server for the tool list and full configuration.

ChatGPT desktop and Codex

After the setup above, register the server with the Codex CLI. Replace /absolute/path/to/virtualdj-api-reference in both arguments with your checkout path:

codex mcp add virtualdj -- \
  /absolute/path/to/virtualdj-api-reference/.venv/bin/python3 \
  /absolute/path/to/virtualdj-api-reference/tools/mcp_server.py

Alternatively, open Settings → MCP servers → Add server, choose STDIO, and enter virtualdj as the name, the absolute .venv/bin/python3 path as the command, and the absolute tools/mcp_server.py path as its argument. Save and select Restart. Local clients on the same Codex host share MCP configuration; the repo's Claude-style .mcp.json is not a substitute for this registration. See the official MCP setup guide.

ChatGPT on the web

The web connection needs a reachable MCP endpoint. For personal use with this local STDIO server, use Secure MCP Tunnel:

  1. Create a tunnel in OpenAI Platform and obtain its tunnel_id. This requires the appropriate Platform tunnel permissions and a runtime API key.
  2. Follow the tunnel guide to install and run tunnel-client on the computer containing this checkout. Configure its STDIO target with the same Python command and server-script argument shown above, and keep the client running.
  3. In ChatGPT, enable Settings → Security and login → Developer mode. Availability depends on your account and workspace policy.
  4. Open Plugins → +, name the connection VirtualDJ, and choose Connection → Tunnel. Select your tunnel or enter its tunnel_id, then create the connection and review the discovered tools.
  5. Start a chat and select the connection from the tools menu.

The tunnel can use the existing server without adding an HTTP listener. Direct URL-based setup instead requires a Streamable HTTP adapter or server at an HTTPS endpoint, with appropriate authentication; this repository does not currently provide that transport. See the official connection guide.

Verify the connection

Run just mcp-check to check the local server, then ask the connected assistant: “Use the VirtualDJ MCP server to show the VDJScript grammar summary.” The local self-check does not establish that a particular ChatGPT connection works.

Reference lookups and linting need no running VirtualDJ. Live queries require VirtualDJ's Network Control extension; use just vdj-up to check it and consult the HTTP Control Interface for setup. Actions are available by default; set VDJ_MCP_READ_ONLY=1 to disable actions and app start/restart for a client. Start/restart otherwise requires VDJ_MCP_RESTART=1. Neither is needed for reference use.

Where to start

Goal File
Answer anything about one verb just verb <name> — the one-screen join: store record, vendor description, real usages, argument shapes with return evidence, every tail candidate by source, vocabulary groups, probe state, each labelled with its evidence tier. just get-verb <name> is the bare store record
Answer "how do I do X" just topic <term> — the matching verbs, effects and XML elements, plus the real example files that use them, ranked by how much of the topic each demonstrates
Pick the next active task TODO.md — recovering the full verb and skin syntax; what already landed is in HISTORY.md, the queue it replaced in RETIRED.md
Route a topic to the right docs and fixtures INDEX.yml
Understand the repo structure and source labeling docs/README.md
Pick the right VDJScript verb or pattern docs/VirtualDJ Reference.md
Look up a specific verb docs/VDJScript Verbs.md
Check official verb coverage docs/Official VDJScript Coverage Audit.md
Choose the next completeness pass docs/Completeness Roadmap.md
Choose or maintain a pad page examples/Pads/README.md
Look up the pad-page XML format docs/Pad Page XML.md
Build skin waveforms docs/Skin Waveforms.md
Browse the rendered reference just build-reference → build/reference/index.html (--open opens it in the browser) (VDJScript verbs and searchable skin elements)
Try the parallel Guides template just build-reference --guides --open → build/reference-guides/index.html (Markdown articles, heading navigation, and section search; original template remains the default)
Browse skin elements / check XML doc coverage just list-skin-elements / just list-skin-elements --family=all --undocumented (data: docs/skin-xml-inventory.json, refreshed by just inventory)
Browse skin categories / observed nesting just list-skin-categories, just list-skin-elements --category=assets, just element button --children, just element text --parents (scope and evidence)
Look up verbs programmatically docs/vdjscript-verb-index.json (generated; just verb-index)
Validate skin/mapper XML just lint-skins [paths] · just lint-mappers [paths] · tools/README.md
Run or update a test harness tests/README.md
Build or study a skin docs/Skin SDK.md · docs/Skin Runtime Findings.md · examples/Skins/README.md · examples/Skins/ModularSkeleton/
Work with effects docs/Effects Usage.md · docs/Native Effects.md
Map a controller or keyboard docs/Mapper XML.md
Write a native plugin, or understand where VDJScript results are still typed docs/Plugin SDK.md
Understand macOS paths and databases docs/Application Internals.md
Inspect or create .vdjstems sidecars docs/Stem File Format.md

The Guides preview uses a separate design/human-api-reference-guides.template.html; the original template remains unchanged. Run just install after updating to install the Markdown renderer. Both default output directories are git-ignored. Guides are rendered from existing Markdown without editing it; links outside the selected guides continue to point into the checkout, so this preview is not yet a standalone site export.

Agent Entry Point

AGENTS.md is intentionally retained for Claude, Codex, and other coding agents that look for that filename. This README.md is the human-facing overview; AGENTS.md keeps the operational shortcuts and repo-specific guardrails.

Reliability

Every fact in the reference docs is labeled by source:

Label Meaning
Official Current VirtualDJ manual or VDJPedia
Official forum Post by VirtualDJ staff, CTO, or support
Community Non-staff forum guidance
Published skin Observed in a working public skin
Built-in skin Observed in skin XML shipped inside the VirtualDJ app bundle
Published pad page Observed in a working public pad page
Built-in pad page Observed in pad-page XML shipped inside the VirtualDJ app bundle
Built-in app resource Command name, description, or UI catalog entry observed in non-skin/non-pad app resources
Verb table VirtualDJ's own serialised verb set, extracted from the binary — decides existence outright
Binary compiled table Structured command metadata observed in compiled executable tables
Binary symbol table Demangled implementation symbols observed in the VirtualDJ executable
Binary string-table Command-looking string observed in the VirtualDJ executable; discovery only
Action catalog The Button Editor's own description for a verb, shipped in languages.zip — the same prose the official appendix publishes, readable offline
Vendor script A form Atomix wrote into a shipped Built-In pad page or skin — attested usage, no probe required
Local test Reproduced in VirtualDJ locally
Inference Conclusion drawn from the above sources

Unlabeled files are raw material not yet normalized to this standard. docs/Evidence Standards.md governs every claim: three tiers, what counts as a behavioral test, and why a channel's own return value is never a result.

Status (2026-09-03)

What a verb's arguments accept is now three-sourced

The reference used to document verb names well and their arguments barely. Three independent sources now cover the tail of a statement, and just action-catalog --cross-check prints them against each other:

  • tests/action-catalog.json — 816 vendor descriptions extracted from the app bundle (languages.zip carries the official appendix's prose, so it is available offline). The only source that says what a parameter means.
  • tests/attested-tails.json — 214 tails Atomix wrote into shipped skins, pad pages and the app's own compiled menu scripts, plus argument shapes (fadeout DUR DUR `BOOL`, param_bigger EXP:NUM EXP:NUM, the deck SEL EXP wrapper) with the return type the vendor's attribute implies, for the verbs whose arguments are values rather than keywords. Attested without a probe, which reaches where no test state can.
  • tests/binary-vocabularies.json — argument vocabularies as groups, recovered from the binary as structures (pointer tables, switch functions): 21 groups, 265 members, of which 189 are named by no per-verb source — the 26 colour names, the 19 settings pages, the 16 stem tokens. The only source that sees an enumeration matched in a shared helper rather than in the verb's own code. Leads, not confirmations.
  • tests/verb-arg-forms.json — every candidate probed against two nonsense controls inside 10 named fixtures, because VirtualDJ silently ignores an argument it cannot parse, so a verb answering proves nothing on its own.

Agreement across all three is the strongest claim this project makes; 10 verbs have it today (just action-catalog --cross-check).

Traps that will bite anyone writing VDJScript, added this cycle

  • A misspelled argument usually makes the action do nothing, and on some verbs degrades to the bare action instead. Neither is reported as an error.
  • Relative and multiplying arguments are execute-only. loop 50% halves a loop rather than setting one, and asking a query for it errors.
  • deck all broadcasts on execute but collapses to deck 1 on query — the same line means two different things depending on position.
  • timecode_cd_mode latches: script can set it and cannot unset it; only a restart clears.
  • The sampler's all means the selected slot, not every slot.

Status (2026-07-30)

VDJScript is no longer a guessing game

The verb set, each verb's contract, and the grammar are now derived from VirtualDJ itself rather than assembled from documentation.

Question Answer How
Is x a verb? Decided, both ways VirtualDJ's own verb table — 1,032 records / 958 distinct verbs / 62 alias groups / 38 editor-hidden on build 18.0.9598 (arm64, extracted 2026-09-05; just verb-table-stamp). Membership proves; absence disproves on that build. just verb-table <name> is the live answer
What category is it in? All of them mapped Compiled Button Editor category tables, confirmed against the live UI
Can it execute / query / return text? All of them ACTION_ class RTTI — a checked 958↔958 bijection of verbs to implementation classes. just verb-contract <name>
What type does it return? 623 of 652 query verbs Live HTTP sweep. just verb-return-type <name>
Does it take arguments? 433 verbs flagged, incl. 300 with optional args E_INVALIDARG fingerprint in each class's own methods
Which keyword arguments? 262 verbs String-comparison fingerprint — recovered get_bpm absolute, browser_window sidelist, loaded opposite and 200+ more that no documentation lists

Traps now documented that will bite anyone writing VDJScript

  • A verb's value is not its truth. get_version reports 2026 and is false as a condition. 171 of 652 query verbs are traps, and no slider verb is ever true.
  • && is not an operator. It never guards anything; it only changes which statement's value a query reports.
  • Chains stop after exactly 255 statements, partially, returning false.
  • GET refuses scripts over ~2,650 characters at the transport layer — which looks exactly like a language failure and caused a documented rule to be wrong for months. Use POST.
  • Chained ternaries are a genuine else-if ladder; each branch takes its whole & chain.

Other areas

  • Skin SDK coverage is broad; the waveform element family is in docs/Skin Waveforms.md, and remaining element gaps are tracked mechanically (just list-skin-elements --undocumented).
  • Controller mapper XML is rewritten around the real <map value=""> + device-definition split, with working mappers in examples/Mappers/Local/. Custom device-definition XML is official-doc-derived and still not load-tested.
  • The VirtualDJ Remote wire protocol is decoded and proven bidirectional (docs/Remote Protocol.md).
  • The plugin SDK is documented (docs/Plugin SDK.md): interface hierarchy, the VDJPARAM_* model and the [autoparams] manifest all 173 built-in plugins use, plugin UI models, and the interfaces present in the binary that the public headers never declare. Headers are third-party with no license grant, so they are fetched to a gitignored vendor/ rather than committed.
  • The native introspection channel is open (2026-08-15). The read-only plugin builds, loads, and has swept every verb-table name through both query callbacks (just plugin-probe <name>, captures in tests/plugin-introspection*.json). It is the boundary where VDJScript results are still typed — GetInfo → double, GetStringInfo → text — which is why HTTP flattens them, and it settled things HTTP structurally cannot: master_beat_num's float-bits defect is in the core, not the transport; a definitive channel map (532 verbs on both callbacks, 67 text-only, 11 numeric-only, 418 on neither); and the HRESULT does discriminate a recognized keyword from an ignored one, which is now the method for the keyword queue because it needs no prepared state.

Recommended next steps

The active queue, TODO.md, is aimed at one thing: the full verb syntax and skin syntax, recovered from the binary through the offline parser and skin hosts. The steps below are the behaviour work it retired; each is a block in RETIRED.md.

  1. Confirm the documented-but-unprobed parameters (task 13b). The fixture harness and argument prober are built and have run: just fixtures lists the named states, just check reports the probe run's verb/form/recognized totals, and just verb-arg-forms <name> shows one verb's. What is left is the state, not the tooling — just action-catalog --cross-check names, under documented_but_not_probe_confirmed, every verb whose parameters the vendor documents and no probe has confirmed, each one a state the existing fixtures never build. Its probe_confirmed_but_undocumented set is the mirror worklist.
  2. Spend the native channel on what only it reaches (task 10a). The plugin is built and the verb sweep is done, so the remaining value is not throughput: GetSongBuffer and OnProcessSamples give the actual PCM behind every waveform element; OnKey(ch, vkey, modifiers, flag, scancode) is the first channel that may expose press/release, which HTTP structurally cannot; VDJINTERFACE_SKIN turns skin testing from edit-and-restart into a loop.
  3. Behavior for most verbs is still untested — just verb-stats gives the current by_test_status breakdown, and Untested dominates it. Existence, kind, category, capability and return type are settled; what a verb does mostly is not.
  4. Audit the remaining Inference and Community labels against docs/Evidence Standards.md, which does not permit either as a standing claim.
  5. Extend the rendered reference (just build-reference) — the verb and skin-element pages exist; per-verb argument evidence and the effects catalog are not rendered yet.

Contributions and corrections welcome. Corrections especially: several long-standing claims were overturned this session by re-testing them on a second channel, and the repo records retractions in place rather than deleting them.

About

Unofficial VirtualDJ documentation for agents and humans

Resources

Stars

2 stars

Watchers

0 watching

Forks

Contributors

Languages