Two emails and a coding agent without touching the keyboard: press Fn, say it, and it's pasted at the cursor. Every take is kept, so the long one can be broken into steps afterward.

Harness is a Mac app I built for myself. It started as my attempt to improve on Siri, Wispr Flow, and other voice tools, and it's grown into a full agentic toolkit: chat, notes, tasks, memory, and image generation, with an iPhone app for capturing ideas on the go.

It's also my test bed for new technologies and interaction patterns. Just as important, I can trace how my data is used, and my thoughts and ideas stay mine, in plain files I can take anywhere.

Speech runs offline on my Mac. The model is a config setting, not the foundation: the notes and conversations are files any model, hosted or local, can read.

If you want to try it, download the latest build (Apple silicon, macOS 12 or later) or read the source.

Plain files

Everything the app keeps is a file on my Mac, in a format I can open without it. Conversations are JSON, notes are Markdown, and every dictation is the original audio. If I stopped using it tomorrow, nothing would be stuck in it.

~/Library/Application Support/Harness/
├─ Conversations/
│  └─ conv_….json               one per conversation
├─ Notes/
│  └─ ….md                      one per note
├─ Recordings/
│  ├─ dictation_recordings.json
│  └─ rec_….wav                 every take, as recorded
└─ .harness/app-state/
   ├─ tasks.json
   └─ user_memory.json          what it remembers about me

Speaking instead of typing

A desktop hotkey for dictating into the computer. Press Fn, talk, press it again, and Apple Speech transcribes the take on the Mac. It works offline and doesn't care if the Wi-Fi is spotty.

It's a full voice recorder, not a walkie-talkie. Push-to-talk trains you into short commands. A recorder that's happy to run for minutes makes room for the long, rambling prompt that actually has the context in it.

The audio is saved before anything else happens, so if transcription or the model fails, the take is still there to run again. After transcription, an editable cleanup pass tidies the text and spells names and terms my way.

One whole take: record, transcribe, clean up, and it's sent with every name spelled right.

On the phone

The iPhone app tries to do one thing well: record. Open it and it's already listening. The home screen is a single circle, and a lock screen widget opens straight into a take.

A finished take is saved as a capture and synced to the Mac, along with chats and tasks, through a Cloudflare R2 bucket that I own. The phone app isn't on the App Store. It builds from the same repo with Xcode.

The iPhone app's home screen: a single white circle on black, with a small menu button at the bottom.
The whole home screen, and what it turns into when I start talking.

Writing to think

Chat stays short. Longer writing goes into a Markdown note that the model can draft into or suggest edits to, and that I keep editing by hand.

A Markdown note titled Week of September 14, with decisions and open questions, beside the library.
A weekly note with decisions and open questions.

Breaking down the work

Ask in chat or dictate, and tasks land in a plain list. There's nothing to set up and no project hierarchy.

The task list: one task under Now, three more active, and two completed.
The task list, with a couple of things already done.