Early accessFor ESP32 boards

Firmware that understands your hardware.

Volt is a typed language for microcontrollers, with an AI assistant built into the IDE. Describe what you want and it writes the program; Volt checks every pin against your chip's datasheet, so a wrong pin is caught there and then, not after an afternoon of debugging.

Free for macOS, Windows and Linux. Prefer a terminal? Install the command line.

Watch it check a program

Scroll, and volt check reads this program against the ESP32-DevKitC's datasheet, flags three pins that would have failed on the board, then applies its own hints.

main.voltESP32-DevKitC
1hardware {2    pin led = 63    pin relay = 344    pin soil: Analog = 255}6setup {7    wifi.connect("home", "secret") or retry(5)8}9every 1s {10    relay.on()11    led.toggle()12    let v = soil.read()13}
Ready Checking pins against the datasheet… 2 errors, 1 warning Applying hints… Check passed in 16ms

Scroll on, or run it yourself.

Problems 3No problems
  1. led

    ErrorFixed main.volt:2

    GPIO 6 is connected to the SPI flash chip. Using it will crash the ESP32.

    Available output pins: 2, 4, 5, 12, 13, 14, 15, 16, 17, 18, 19, 21, 22, 23, 25, 26, 27, 32, 33

    Moved from GPIO 6 to GPIO 2.

  2. relay

    ErrorFixed main.volt:3

    GPIO 34 is input-only — cannot be used as Output.

    Input-only pins: 34-39.

    Moved from GPIO 34 to GPIO 18.

  3. soil

    WarningFixed main.volt:4

    GPIO 25 is on ADC2, which is BLOCKED while WiFi is active. Analog reads will return errors or garbage.

    Use ADC1 pins instead (GPIO 32-39) which work with WiFi.

    Moved from GPIO 25 to GPIO 34.

ESP32-DevKitC V4 board, top view, with both 19-pin headers labelled EN BOOT ESP32-DevKitC V4 ESP32-WROOM-32 ESPRESSIF 3V3 EN VP VN 34 35 32 33 25 26 27 14 12 GND 13 D2 D3 CMD 5V GND 23 22 TX RX 21 GND 19 18 5 17 16 4 0 2 15 D1 D0 CLK
main.volt
1hardware {2    pin led = 23    pin motor: PWM = 44    pin battery: Analog = 355}67setup {8    wifi.connect("home", "secret") or retry(10)9    mqtt.connect("mqtt://broker.local") or retry(5)10}1112task blink {13    every 500ms { led.toggle() }14}1516task report {17    every 5s {18        mqtt.send_int("volt/battery", battery.read())19    }20}2122task drive {23    every 1ms strict { motor.set_pwm(512) }24}
Task trace over 6 seconds drive fires every millisecond from a hardware timer, a continuous band at this scale; blink toggles the LED every 500 ms; report sends once at 5 seconds and blocks on the network in its own FreeRTOS task. blink still toggles at 5.5 seconds and drive never pauses during report's wait. 0123456 s report blocks on the network; blink and drive keep time drive timer ISR, 1 kHz report FreeRTOS task blink protothread 0.00 s

Tasks run in parallel, and Volt decides how

Write each job as its own task and they all run at once. The compiler reads each body and picks the cheapest way to run it safely, so a blink loop never pays for a FreeRTOS stack and a network call never stalls your motor control.

State machines are part of the language

States, guards, timeouts and entry and exit actions are syntax, not a library. Doors reopen when the beam is broken, the emergency stop halts the car from any moving state, and the checker verifies every transition and flags states that can never be reached.

elevator.volt
1// hardware, floor and call-button polling omitted2machine elevator {3    initial state idle {4        on target > floor -> going_up5        on target < floor -> going_down6    }78    state going_up {9        enter { motor_up.on() }10        exit { motor_up.off() }11        on estop.is_pressed() -> stopped12        on floor == target -> doors_open13    }1415    state going_down {16        enter { motor_down.on() }17        exit { motor_down.off() }18        on estop.is_pressed() -> stopped19        on floor == target -> doors_open20    }2122    state doors_open {23        enter { door_open.on() }24        exit { door_open.off() }25        after 5s -> doors_closing26    }2728    state doors_closing {29        enter { door_close.on() }30        exit { door_close.off() }31        on beam.is_pressed() -> doors_open32        after 3s -> idle33    }3435    state stopped {36        on reset.is_pressed() -> idle37    }38}
elevator: idle goes up or down toward the target floor; arriving opens the doors; after 5 s the doors close, reopening if the beam is broken, and after 3 s it returns to idle; the emergency stop halts either moving state until reset idle going_up motor_up.on() stopped going_down motor_down.on() doors_open door_open.on() doors_closing door_close.on() target > floor target < floor estop estop reset floor == target (both) after 5s beam after 3s

Pins that look free can crash the ESP32

Under the module's metal can, the SPI flash that stores your program is wired to GPIO 6–11. The DevKitC breaks them out as CLK, D0–D3 and CMD. They look like free pins. Wire anything to one and the ESP32 crashes the moment it tries to read its own code.

Volt checks every pin against the datasheet and stops you before you build:

-- HARDWARE ERROR -- main.volt:2

GPIO 6 is connected to the SPI flash chip.
Using it will crash the ESP32.

Volt IDE

Describe what you want and the assistant writes it. The checker runs on every edit, the wiring view shows what goes where, and the same window builds, flashes and opens the serial monitor.

Go on, put

Upload Monitor ESP32-DevKitC File Compile Settings Help
Code Wiring Diagrams ESP32smart-gardenmain.volt
Output Serial Monitor Problems

    No problems. Every pin is safe to use on this board.

    Loading the checker… Volt checker · WebAssembly

    Wrong pins, caught as you type

    Hover a pin to see what it is on your board. Pins that can’t do the job are underlined before you build.

    Hovering GPIO 34 in Volt IDE: left header pin 5, analog, input-only, so it cannot be used as an output
    The assistant explains why an upload failed and offers to flash once the board is connected

    An assistant that asks first

    Claude Code or Codex, built in. It explains each step and waits for your go-ahead.

    The door lock's state machine drawn from the code: locked, unlocked and alert with their transitions

    Diagrams from your code

    Every state machine is drawn as you write it.

    History panel listing each saved change to main.volt with lines added and removed

    Undo anything

    Every save and every assistant edit lands in History, ready to restore.

    Device libraries, checked

    Sensors, displays and radios with typed methods, so a wrong call is an error, not a guess.

    Volt IDE's device library: installed drivers listed on the left and a search for sensors, displays and chips

    Coming from Arduino or ESP-IDF

    From Arduino

    setup works the way you expect. Timed blocks like every 500ms replace millis() bookkeeping, and they run side by side without you writing a scheduler.

    From ESP-IDF

    Volt builds on ESP-IDF and FreeRTOS. You keep native performance and stop maintaining task handles, stack sizes and pin-mux tables by hand.

    Questions

    Short answers about boards, the licence, the assistant and your data.

    Read the docs →
    Is Volt free?

    Yes. Volt is open source under the GPL and AGPL. If those terms don’t fit your product, a commercial licence is available.

    Which boards does it support?

    ESP32 boards today, starting with the ESP32-DevKitC. RP2040 and STM32 are next.

    Do I need to be online?

    No. Checking, building and flashing all run on your computer. Only the assistant needs a connection, through your own Claude Code or Codex sign-in.

    Does Volt IDE collect data?

    It sends crash reports and anonymous usage statistics (IDE version, OS, chip, which features you use and whether builds succeed) under a random install ID. Never your code, files or project names. Both are on by default and can be turned off in Settings › Privacy. Details are on the privacy page. Privacy →

    Where do I get help?

    Ask in the Volt Discord, or use Help › Send Feedback in the IDE to reach the team directly. Join the Discord →

    Can I use the C drivers I already have?

    Yes. A device library is a small folder: a list of the device’s methods and a C driver. Wrap the driver you have and Volt checks every call to it.

    Do I have to use the assistant?

    No. The language, checker and IDE work without it. When you do use it, it asks before doing anything outside your program, and every change it makes can be undone from History.

    Can I sell products built with Volt?

    Yes. Your code is yours. Firmware includes Volt’s runtime, so for a closed-source product, use the commercial licence.

    Put Volt on your board.

    Download Volt IDE, plug in an ESP32 and press Upload. The command line comes with it.

    All downloads · Volt IDE 2.0.86

    SystemFileSize
    macOS 12 or later, Apple silicon Disk image 171 MB
    macOS 12 or later, Intel Disk image 178 MB
    Windows 10 or later, 64‑bit Installer 146 MB
    Linux, 64‑bit AppImage 176 MB
    Debian and Ubuntu, 64‑bit Package (.deb) 143 MB

    The Windows installer isn't code-signed yet, so Windows may show a SmartScreen warning the first time it runs: choose More info, then Run anyway.

    For advanced users: to install only the volt command line on macOS or Linux, run:

    curl -fsSL https://voltembedded.com/install.sh | sh