Install, update and find your files

Reference for installing ParrotFlow with Homebrew or the install script, how updates work, and where the config, transforms, recordings and log live.

ParrotFlow needs Apple silicon and macOS 15 or later. It uses about 3 GB of disk and about 1 GB of memory. For a short version of this page, see Download.

Install with Homebrew

brew install znat/tap/parrotflow

The cask lives in znat/homebrew-tap. It reads the checksum from the published release. It sets auto_updates true, because the app installs its own updates.

The cask also links the binary onto your PATH as parrotflow. Use it for the command line flags, for example parrotflow --check-config. The install script does not add this command. If you used the script, write the full path /Applications/ParrotFlow.app/Contents/MacOS/ParrotFlow wherever this page says parrotflow.

Do not use parrotflow to start the app. With no arguments in a terminal, it prints how to start the app and exits with code 2. A copy started from a shell gets permissions credited to the shell, not to ParrotFlow. Start the app like this:

open -a ParrotFlow

Install with the script

curl -fsSL https://raw.githubusercontent.com/znat/parrotflow/main/scripts/install.sh | sh

The script downloads ParrotFlow.zip from the latest GitHub release, installs ParrotFlow.app in /Applications and starts it. The download is about 3 MB.

If /Applications is not writable, install somewhere else with PARROTFLOW_DEST:

curl -fsSL https://raw.githubusercontent.com/znat/parrotflow/main/scripts/install.sh | PARROTFLOW_DEST=~/Applications sh

If the download fails, check that a release exists on the releases page.

What the script checks

The script and the app’s own updater check a download the same way, in the same order. Nothing is installed until every check passes.

  1. The published SHA-256 matches the archive.
  2. codesign --verify --deep --strict says the signature covers the whole bundle.
  3. codesign -R says the certificate was issued by Apple to the ParrotFlow team.
  4. spctl --assess --type execute says Apple notarized it.

You do not need to turn off Gatekeeper, remove the quarantine attribute or use sudo. If something seems to need one of these, something else is wrong.

Check the install

--check-config validates the config and prints what the app will use. It also reports the microphone permission.

parrotflow --check-config

It cannot report Accessibility. macOS credits a check made from a terminal to the terminal, so it reads as missing even when it is granted. The app checks it at launch and writes the result to its log:

grep "launched —" ~/Library/Logs/ParrotFlow.log | tail -1

You want accessibility=Granted. See Permissions.

To check transcription without speaking, make a test clip with say and transcribe it:

say -o /tmp/pf-check.wav --data-format=LEI16@16000 --channels=1 "Testing one two three"
parrotflow --transcribe /tmp/pf-check.wav

The first run downloads the speech model. Any text that comes back means transcription works.

Update

The app checks GitHub for new releases and offers them in a panel with the release notes. You have three answers:

  • Update and restart downloads, checks and replaces the app.
  • Skip this version never offers that version again.
  • Later.

The check sends nothing about you or what you dictate. updates.after_days in config.yaml sets how long a release must exist before it is offered:

updates:
  after_days: 7    # 0 offers a release the day it ships (default); -1 never asks

You can also update by running the install command again. It replaces the app in place. This is the way in when the app cannot install over itself.

From a terminal:

parrotflow --update-check [--after-days N]
parrotflow --update-install [--dry-run]

Releases are signed with the same certificate, so an update keeps your Microphone and Accessibility grants.

Upgrading from v0.9.0 or older

Releases up to v0.9.0 were signed with a self-signed certificate. Later releases use a Developer ID, which is a new identity. The updater in those old releases refuses the new build. Run the install command again, or install with Homebrew. You then grant Microphone and Accessibility once more.

Where files live

What Where
App /Applications/ParrotFlow.app
Config ~/.config/parrotflow/config.yaml, created on first launch
Vocabulary ~/.config/parrotflow/vocabulary.yaml
Your transforms ~/.config/parrotflow/transforms/<name>/, one folder each
Built-in transforms ~/.config/parrotflow/transforms/built-in/, refreshed from the app on every launch
Recordings ~/.config/parrotflow/recordings, empty unless logging.audio: true
Trace ~/.config/parrotflow/recordings/trace.jsonl
Timeline ~/.config/parrotflow/recordings/spans.jsonl
Log ~/Library/Logs/ParrotFlow.log
Python for parsing ~/Library/Application Support/ParrotFlow/python, about 170 MB
API keys your keychain, under the service ParrotFlow

Do not edit files in transforms/built-in/. The app replaces them on the next launch. To change a built-in transform, copy its folder into transforms/<name>/ and point command: at the copy.

The app reloads config.yaml and vocabulary.yaml when you save them. No restart is needed.

Set PARROTFLOW_CONFIG_DIR to point the command line flags at another config directory. The app reads it too, so do not export it from your shell profile.

When something goes wrong

Most answers are in the log. Every start records the key and both permissions. Every clip records whether speech was found and what was transcribed.

tail -30 ~/Library/Logs/ParrotFlow.log

If System Settings shows a permission as granted but the app disagrees, see Reset a permission.

--bug-report prints the version, macOS, the chip, the permission state, the --check-config output and the last 50 lines of the log. Home paths are written as ~.

parrotflow --bug-report

The full reference is in setup.md and distribution.md on GitHub.