# yap turns Speech.framework into a transcription pipeline tool

> A Swift CLI that runs on-device transcription on macOS 26, with four subcommands for files, system audio, microphone and both at once, four output formats, and an MCP server so an agent can call it. It is fast because nothing leaves the machine.

**finnvoor/yap** — 🗣️ A CLI for on-device speech transcription using Speech.framework on macOS 26

- Repository: https://github.com/finnvoor/yap
- Stars: 1,630 · Forks: 69
- Language: Swift
- License: CC0-1.0
- Published: 2026-10-16 · Updated: 2026-10-16 · Language: en
- Canonical page: https://hysenlabs.com/projects/finnvoor-yap

## Four subcommands, and only one of them takes a file

yap is described as a CLI for on-device speech transcription using Speech.framework on macOS 26, and it presents itself as four distinct subcommands rather than one command with modes.

The transcribe subcommand is the ordinary one. It takes an input file described as a path to an audio or video file to transcribe, which is why the examples pass a.mp4 straight in. The other three are live: listen transcribes system audio in real time, anything playing on the computer; dictate transcribes microphone input in real time; and listen-and-dictate captures both simultaneously, which the README positions as meeting transcription.

The split matters because the permission requirements differ by subcommand, not by flag. File transcription needs none of the privacy grants. listen needs Screen Recording permission. dictate needs Microphone permission. listen-and-dictate needs both, and the README tells you to grant them to your terminal app under System Settings > Privacy & Security.

The documented permission grants should therefore be applied to your terminal app.

## Install is one line through Homebrew or Mint

Two package managers are documented, both Swift-native workflows.

```bash
brew install yap
```

The alternative installation command uses Mint.

```bash
mint install finnvoor/yap
```

The repository is a Swift package: Package.swift and Package.resolved at the root, Sources/ holding the code, and a.swiftformat configuration for formatting. Package.resolved being committed pins the dependency versions, which is the convention for an application rather than a library.

There is no configuration file and no model download step documented. Everything routes through Speech.framework, which is part of the operating system, so the absence of a model artefact is consistent with the on-device claim.

The licence is CC0-1.0, a public domain dedication rather than a permissive licence with a notice requirement. That is a stronger grant than MIT and an unusual choice for software.

## Four output formats, and max-length is a segmentation control

Output format is a flag group: --txt, --srt, --vtt and --json, defaulting to --txt. If no output file is given with -o, the result goes to stdout, which is what makes the pipe examples in the README work.

The subtitle formats are the reason to care about this flag rather than piping text. An SRT file for a video is one command.

```bash
yap video.mp4 --srt -o captions.srt
```

WebVTT is the same idea with the .vtt extension.

```bash
yap video.mp4 --vtt -o subtitles.vtt
```

What ties the formats together is --max-length, described as the maximum sentence length in characters with a default of 40. In the timed subcommands the help text is more specific: it is the maximum sentence length for timed output formats. So the value is a segmentation parameter, not a truncation limit, and it controls how long a caption cue is allowed to run before the transcript is broken.

For the live subcommands, --word-timestamps adds word-level timing to JSON output, which is what lets a meeting transcript be aligned against a recording later.

## The examples assume you will pipe the text somewhere else

The README's examples are less about transcription than about composition. The first hands a YouTube download straight to yap.

```bash
yt-dlp "https://www.youtube.com/watch?v=ydejkIvyrJA" -x --exec yap
```

The second pipes plain text into a language model run through llm, which is a good illustration of the shape: yap is the text producer, not the summariser.

```bash
yap video.mp4 | uvx llm -m mlx-community/Llama-3.2-1B-Instruct-4bit 'Summarize this transcript:'
```

The live modes compose the same way, with yap listen piped into llm for translation.

```bash
yap listen | uvx llm 'Translate this to French:'
```

## Speaker labels only exist on the two-source subcommand

listen-and-dictate is the only subcommand with --mic-label and --system-label, and the help text is clear that they apply to timed output formats. The defaults are Mic and System.

```bash
yap listen-and-dictate --vtt --mic-label Alice --system-label Bob > meeting.vtt
```

This is a small design decision with a large effect on the output. A two-speaker meeting transcribed into a flat text stream is much harder to read later, and the label options exist so the timed formats can separate the two sources. Note the constraint, though: the labels are documented as applying to timed output formats, so do not assume a plain .txt dump will carry the same speaker attribution.

The other option on this subcommand is --censor, which appears on all four subcommands and replaces certain words and phrases with a redacted form. The README does not enumerate which words or phrases, or how the list is configured, so treat it as a fixed behaviour of the tool rather than a policy you control.

## An MCP server, which is the part that changes how it gets used

yap includes a Model Context Protocol server exposing a transcribe tool, so any MCP-compatible agent can transcribe audio and video files through it. The registration is a single command for each client.

```bash
claude mcp add yap -- yap mcp
```

```bash
codex mcp add yap -- yap mcp
```

The mcp subcommand is not documented with a usage block of its own in the README, which means the tool schema, its parameters and whether it accepts the same --locale or format flags as the CLI are not described there.

That is the gap to be aware of if you plan to use it as an agent tool: the transcribe tool's surface is defined by the MCP implementation rather than by the CLI help text you can read here. The upside is straightforward. Because transcription stays on device, an agent can be given a long audio file and a summarisation task without the audio leaving the machine, which is the same property the CLI examples rely on.

## Platform lock-in is the whole design, not an accident

Every path through this tool goes through Apple's Speech framework on macOS 26. That is stated in the first line of the README and it is not a limitation anyone intends to remove; it is where the on-device guarantee comes from.

The consequences follow. There is no Linux build and no Windows build in the documented installation options, which rules yap out of a cross-platform transcription pipeline where the first stage is the same everywhere. There is also no way to plug in a different recognition model through configuration, because no model option is documented.

The locale flag is documented for every subcommand and defaults to the current locale.

For a macOS-only shop that wants private, no-API-cost transcription, that is a good trade. For anything else, the constraint ends the evaluation early.

## Maintenance and versioning

The repository is not archived and the last push was on 2026-07-20. Releases are close behind that: 1.2.1 on 2026-07-20, 1.2.0 on 2026-02-15 and 1.1.0 on 2026-02-10.

The version numbers are small and the release dates show a project that adds subcommands rather than stabilises an API, which is consistent with a CLI whose surface is the help text. 

Because it ships through Homebrew and Mint rather than as a library dependency, upgrading is a package manager operation and there is no API compatibility to reason about for consumers.

The CC0-1.0 licence is the one item to check if you plan to fork it. Public domain dedication means no attribution requirement, which is simpler than MIT for most uses and worth confirming against your organisation's policy on incorporating CC0 code.

## Conclusion

Adopt yap if you work on macOS 26 and want transcripts that never leave the machine, since everything runs through the on-device Speech.framework path and the SRT, VTT and JSON outputs feed directly into captioning and indexing tools. Do not adopt it if you need Linux or Windows support, or if you need a daemon that stays resident, because the documented interface is one-shot command line invocation plus streaming modes that live in your terminal. Verify first the permissions your terminal needs, Screen Recording for system audio and Microphone for dictation, and check that the audio file formats you plan to feed in are handled by Speech.framework on your macOS version before building a pipeline around it.

## FAQ

### Does yap send audio to a server?

The README describes yap as a CLI for on-device speech transcription using Speech.framework, and the summarisation example runs an MLX community model locally. Nothing in the documented options sends audio or transcript to a remote service.

### Which permissions does yap need for live system audio?

Screen Recording permission for your terminal app, granted under System Settings > Privacy & Security > Screen Recording. The dictate subcommand needs Microphone permission instead, and listen-and-dictate needs both.

### How do I create SRT or WebVTT subtitles with yap?

Pass the format flag and an output path, for example yap video.mp4 --srt -o captions.srt for SRT and yap video.mp4 --vtt -o subtitles.vtt for WebVTT. Without -o the output goes to stdout. The --max-length option, defaulting to 40 characters, controls maximum sentence length in timed output formats.

### Can an AI agent call yap?

Yes. yap includes an MCP server exposing a transcribe tool, and you register it with a client such as claude mcp add yap -- yap mcp or codex mcp add yap -- yap mcp.

## Sources

- [finnvoor/yap on GitHub](https://github.com/finnvoor/yap)
- [Issues](https://github.com/finnvoor/yap/issues)
- [License: CC0-1.0](https://github.com/finnvoor/yap/blob/main/LICENSE)
- [README](https://github.com/finnvoor/yap/blob/main/README.md)
- [Releases](https://github.com/finnvoor/yap/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/finnvoor-yap
