A simple USB macropad with 8 programmable buttons.

Motivation / Project requirements

  • I want to have a simple macropad I can use to control my computer.
  • I want to be able to write userspace programs in Golang, that will react to the keypress events in the macropad and execute some Golang code, instead of building long sequences of keypress macros.
  • I want the PCB to be simple (PTH parts only), to have only the buttons and a single indicator LED, and to use the simplest/smallest microcontroller that can handle USB 1.1 and 8 buttons, like the ATtiny4313.
  • I want the enclosure to be 3D-printable at home.
  • I want the firmware to be as USB HID compliant as possible, so I can learn more about the USB stack and specifications.
  • I want the client library to support at least Linux and Windows.


After using the original octokeyz macropad for a few months I realized that having a small OLED screen added to it could be very useful. This new addition required using a more powerful microcontroller (I picked the STM32F042K6/STM32F042K4, which is not PTH, but still quite easy to hand-solder).

These additions resulted in a new octokeyz macropad variant named octokeyz-mega, that also includes support for 5-pin mechanical keyboard switches instead of the simpler 12mm SPST push-buttons used in the original variant.

Given the low price of the STM32 microcontrollers nowadays, and to simplify the project maintenance, I ended up converting the original octokeyz variant to also use the STM32F042K6/STM32F042K4 parts. This way we can deploy the same DFU-capable firmware to any of the board variants.



The following resources are common to all variants:


octokeyz-mega Front
octokeyz-mega Top
octokeyz-mega Side


octokeyz Front
octokeyz Top

Program examples


package main

import (


func main() {
	dev, err := octokeyz.GetDevice("")
	if err != nil {

	if err := dev.Open(); err != nil {
	defer dev.Close()

	for i := 0; i < 3; i++ {
		time.Sleep(100 * time.Millisecond)

	dev.AddHandler(octokeyz.BUTTON_1, func(b *octokeyz.Button) error {
		duration := b.WaitForRelease()
		fmt.Printf("released. pressed for %s\n", duration)
		return nil

	if err := dev.Listen(nil); err != nil {


How to implement a more complex client software?

Please check the Golang API documentation.

How to use this macropad to control OBS, similarly to what the Stream Deck does?

It is possible to write Golang code that interacts with OBS by using the goobs library: https://github.com/andreykaipov/goobs. This library could be easily integrated with our Golang client library.