Skip to Content
Docs

Your first app

Install mixel, make a small app that folds songs to mono, test it, and open it in Mixel. About five minutes.

View as Markdown

You need two things:

  • Mixel on a Mac with macOS 14 or later. Download it.
  • uv, which installs mixel and your app's Python packages.

Nothing else: no Node, and no Python setup of your own. mixel also runs on Linux and Windows, where everything but mixel dev works.

Install mixel

uv tool install ox1audio
mixel doctor

The package is ox1audio; the command it installs is mixel. mixel doctor says what's missing, if anything, and how to fix it.

These pages describe mixel 0.3.5 or later; mixel --version says which you have, and uv tool upgrade ox1audio updates it. To use the SDK in a script of your own, pip install ox1audio works too.

Start an app

mixel new "Make It Mono"
cd make-it-mono

That writes a small app that already passes its checks:

FileWhat it's for
app.pyThe actions: the work, as Python functions
app.jsonThe name, a one-line summary, and what the app may touch
AGENTS.mdThe whole API, for you and your coding agent
tests/test_app.pyA test that runs the action on tests/tone.wav
pyproject.tomlThe Python packages the app needs

Write the action

Replace app.py with this:

app.py
import numpy as np

import ox1audio as ox


@ox.action("Make it mono")
def mono(files: ox.Files("audio")):
    made = []
    for i, path in enumerate(files):
        ox.progress(i / len(files), path.name)
        samples, rate = ox.audio.read(path)
        folded = np.mean(samples, axis=1, keepdims=True)
        out = ox.audio.write(folded, rate, "wav", name=f"{path.stem} mono")
        made.append(ox.sound(out, title=f"{path.stem} mono"))
    return made
  • files: ox.Files("audio") becomes a file picker. Each path is a pathlib.Path.
  • ox.progress moves the progress bar, and it's where Stop takes effect.
  • Each ox.sound goes into the person's Library when the action returns.

ox.audio.read hands you the samples as a numpy array, and the app imports numpy, so list it as a package. (mixel check --fix adds it for you.)

pyproject.toml
[project]
name = "make-it-mono"
version = "0.1.0"
requires-python = ">=3.11"
dependencies = ["numpy"]
uv sync

uv sync installs numpy into the app's .venv and writes uv.lock, which pins the exact versions. mixel runs your app with this .venv, and Mixel installs exactly what uv.lock pins for the person, so commit it with the app.

Say what it does

Open app.json and write the words people will read. The summary is what they see in Mixel's Apps section, and each permission's reason appears before the app opens:

app.json
{
  "$schema": "https://0x1audio.com/schema/app/v1.json",
  "name": "make-it-mono",
  "displayName": "Make It Mono",
  "summary": "Fold stereo songs down to one channel.",
  "version": "0.1.0",
  "sdk": "^0.3",
  "entry": "app.py",
  "permissions": {
    "files": "Open the songs you choose.",
    "library": "Save the mono copies to your Library."
  },
  "accent": "#20b4c4"
}

Check and test

The test mixel new wrote is for the app it started with, so change it to test your action:

tests/test_app.py
import unittest
from pathlib import Path

import ox1audio as ox

import app

TONE = Path(__file__).with_name("tone.wav")


class MonoTest(unittest.TestCase):
    def test_makes_a_mono_copy(self):
        run = ox.test(app.mono, files=[TONE])
        item = run["items"][0]
        self.assertEqual(item["title"], "tone mono")
        self.assertEqual(ox.audio.probe(item["path"]).channels, 1)


if __name__ == "__main__":
    unittest.main()

Then check the app, run its tests, and run the action once on the test tone:

mixel check
mixel test
mixel run mono --file tests/tone.wav --out /tmp/mono

mixel check applies the rules Mixel and its reviewers use. When something's wrong, it names the file and line, then a fix: line that tells you what to change. mixel run runs one action on a real file and leaves the result in /tmp/mono for you to listen to.

Open it in Mixel

In Mixel, turn on Settings › Developer mode, then quit Mixel and open it again: the switch takes effect the next time it opens. Then:

mixel dev

The app opens in Mixel, marked In development. Save app.py and it reloads. Anything it prints, and every error, shows up in your terminal. Press Ctrl-C to close it.

Make It Mono in Mixel: one song chosen, and a mono copy saved to the Library

Mixel drew the form from the function: a file picker for files, and a button named after the action. When you want more than a form, add a page.

Next

On this page