Blog ยท

Build a transcription app with utt

utt already handles the microphone, speech model, permissions, and text processing. Connect your app through HTTP or local files.

Adding speech recognition to an app means more than running a model. You also have to handle microphone permissions, audio formats, background threads, device changes, and sleep.

utt already handles that work. It runs Parakeet and Whisper on the Mac, keeps audio on the Mac, and applies the user's replacements, cleanup, and formatting.

Your program can connect in two ways. Use the HTTP API for audio from another process or device. Use an extension for a local program that needs transcripts, filters, settings, or status.

Send audio over HTTP

Turn on the API in Settings, then send an audio file to POST /transcribe. utt returns JSON. The request body is the file itself, so you do not need an SDK or multipart form.

curl

curl -X POST http://mac.local:8756/transcribe \
  -H "Authorization: Bearer $UTT_TOKEN" \
  -H "Content-Type: audio/wav" \
  --data-binary @clip.wav

The text that comes back has been through the same pipeline the hotkey uses, including the user's own replacements and formatting rules. Your app gets exactly what utt would have pasted.

Any program that can make an HTTP request can use the API, including shell scripts, Raycast commands, Shortcuts, and apps on your local network. The developer guide includes working examples in Swift, Python, and JavaScript.

Connect a local extension

A local program can add its own page to utt by writing one JSON manifest. utt draws the settings and actions on the page, then stores the user's choices in a values file the program can read.

Extensions exchange audio and transcripts with utt through files. They do not need to open a port or store an API token.

Every new extension starts pending. utt shares nothing until the user reviews its requests and approves it.

The example below writes a local recording to the extension's jobs folder. utt writes the transcript beside it.

Python

jobs = Path.home() / "Library/Application Support/dev.jurrejan.utt/extensions/deckhand.jobs"
part = jobs / "clip-1.wav.part"
part.write_bytes(wav)
part.rename(jobs / "clip-1.wav")  # now utt sees it

answer = jobs / "clip-1.json"
while not answer.exists():
    time.sleep(0.2)
result = json.loads(answer.read_text())
answer.unlink()
print(result.get("text") or result["error"])

Use the jobs folder when a program on the same Mac needs transcription without a server, token, or network access.

What you can make with an extension

The manifest lets a program use one part of utt or combine several:

  • An audio source drops local recordings into a jobs folder and reads the finished text.
  • A transcript consumer receives every completed transcript to save it, route it or act on it.
  • A live companion follows provisional words while the key is held and receives the final transcript later.
  • A text filter rewrites, translates, formats or stops a transcript before utt delivers it.
  • A control surface puts settings, actions, status, daemon health and an optional submenu inside utt.

A companion that also needs the HTTP API can ask utt to put the token in its values file after the user approves it. The developer guide maps every kind to its manifest keys and files.

Build it with an LLM

The API and Extensions pages in utt each have a Copy guide button. It copies the exact protocol, audio settings, a working example, and common mistakes into a brief written for coding assistants.

Paste the brief into Claude, Cursor, Codex, or another coding assistant. Then describe the program you want:

Build me a small app that watches my Voice Memos folder. Every new recording goes to utt, and the transcript is saved as a text file next to it.

The brief gives the model the exact utt protocol, so you can focus on what your program should do.

The API guide leaves the token as a placeholder. Copy it from utt's API settings after the code exists instead of pasting the secret into a chat.

Deckhand

Deckhand lets you control Claude Code sessions on your Mac from an iPhone. Choose a session, read its latest reply, and hold to talk. utt transcribes the recording on your Mac, then Deckhand sends the text to that session.

Where to start

  1. Install utt and dictate something, so you know what it does.
  2. Open Settings. Under Connect, switch on the API, or open the Extensions page.
  3. Press Copy guide and paste it into your model, or read the developer guide yourself.
  4. Build your app.

If you publish an extension, open a GitHub issue with the repository link to have it added to the Extensions page.