Skip to content

Mac Apps

freeflow-james

A Mac menu bar dictation app — free, open-source alternative to Wispr Flow, Superwhisper, and Monologue. Hold Fn to talk, or tap Command-Fn to toggle, and whatever you say gets pasted into the active text field with AI cleanup.

This repo (freeflow-james) is James’s daily-driver fork. It tracks zachlatta/freeflow as upstream and carries personal customizations (UI tweaks, behavior changes, experiments) that may or may not flow back upstream as PRs.

  • All day, every day. This is the dictation engine that powers James’s voice-first input — most of what hits Wispr Flow’s old slot now hits FreeFlow.
  • For Edit Mode work — highlight existing text, speak an instruction like “make this shorter” or “turn this into bullets,” and FreeFlow rewrites it in place.
  • When you want context-aware cleanup — FreeFlow can read the surrounding app context so names, jargon, and project terms come back spelled correctly.
  1. App lives in the menu bar. Hotkeys are configurable in Settings.
  2. Hold the talk key, speak. Audio routes to the configured transcription provider (Groq by default, OpenAI-compatible API).
  3. Cleanup pass — a Claude-style LLM call that uses surrounding app context plus your custom vocabulary to fix names, terms, and phrasing.
  4. Text gets pasted into the focused field. No FreeFlow server in the middle, so audio + cleanup go provider → your Mac, nothing stored upstream.
  • Daily-driver repo: ~/apps/freeflow-james/ (this one — what James actually runs)
  • PR-staging fork: ~/apps/freeflow/ (ojhurst/freeflow on GitHub — clean branches off upstream, used to send improvements back to zachlatta/freeflow)
  • Bundle path on disk: /Applications/FreeFlow James.app
  • Bundle ID: com.zachlatta.freeflow.dev — unchanged from upstream so TCC permission grants survive merges.

freeflow-james is for everything James runs every day, including changes that may never go upstream.

freeflow is for sending PRs back. Branch off upstream/main, apply ONLY the change you want to propose, PR that branch to zachlatta/freeflow. Keeps personal-only customizations out of upstream.

The Makefile defaults to CODESIGN_IDENTITY ?= FreeFlow Dev which expects a self-signed cert that does not exist on James’s machines. Always build with the Apple Development cert:

CODESIGN_IDENTITY="Apple Development: ojhurst@gmail.com (FKLXWDKTW3)" make

Why this matters: ad-hoc signed builds get a different cert hash on every rebuild, which breaks TCC permission grants (Accessibility, Screen Recording, Microphone). Apple-signed builds keep a stable hash so grants persist.

The Apple cert’s private key ships with an interactive ACL. codesign works from a Terminal James is physically logged into, but fails with errSecInternalComponent from SSH sessions, Claude Code’s Bash tool, or anything else without an attached UI. Run this once per machine in a local interactive Terminal:

bash ~/apps/cc/bin/unlock-keychain-acl.sh

Idempotent. After it succeeds, codesign with the Apple Development cert works from any caller, including Claude’s Bash and SSH sessions. Repeat on every machine that holds the cert (Studio + MBP).

When Claude Is SSH’d From A Different Machine

Section titled “When Claude Is SSH’d From A Different Machine”

If Claude is on Studio but James is at MBP, do NOT try to build + sign on Studio — Claude’s Bash there has no UI keychain auth and codesign will fail with errSecInternalComponent. Instead, push the source from Studio and route the entire build through an interactive Terminal on MBP via:

bash ~/apps/cc/bin/run-terminal-over-ssh.sh mbp /tmp/freeflow-build-deploy.sh

That Terminal has UI keychain auth, codesign succeeds, and the deployed .app lands on the machine James actually uses.

git fetch upstream
git merge upstream/main

Resolve conflicts carefully — James’s local customizations may overlap with upstream changes.

  • App name on disk is FreeFlow James.app, distinct from the upstream FreeFlow Dev.app. Bundle ID stays upstream’s so TCC carries over.
  • Privacy: there is no FreeFlow server. Audio and prompts go to the configured transcription + LLM provider (Groq by default), nothing else.
  • Edit Mode is opt-in in settings — when off, FreeFlow only inserts new text, never rewrites existing selections.