vincent on macOS
Apple silicon and Intel are both released and both exercised in CI.
Install
brew install lezli01/tap/vincent
Or double-click vincent_*_darwin_universal.pkg from the release page — one
universal installer for both architectures, putting the binary at
/usr/local/bin/vincent.
Or unpack the release archive by hand:
tar -xzf vincent_*_darwin_arm64.tar.gz # or _darwin_amd64 on Intel
sudo mv vincent /usr/local/bin/
vincent version
~/.local/bin works just as well if you would rather avoid sudo. Full
detail, including signature verification:
Installation.
Gatekeeper
There is nothing to do. Every macOS artifact — the binaries inside both
archives, and the .pkg — is signed with an Apple Developer ID identity under
the hardened runtime, and notarized by Apple. Gatekeeper clears a downloaded
release on its own, so there is no “cannot be opened because it is from an
unidentified developer” dialog and no quarantine attribute to strip.
If you have older instructions that say to run xattr -d com.apple.quarantine,
delete them. Stripping the attribute now only turns off the check that would
have told you the file had been tampered with.
Check for yourself, on the binary you are about to run:
codesign --verify --strict --verbose=2 /usr/local/bin/vincent
spctl --assess --type execute -vv /usr/local/bin/vincent
spctl should report accepted with source=Notarized Developer ID. That
check reaches Apple over the network: the ticket for a bare binary is served by
Apple rather than carried inside it, because a Mach-O has nowhere to staple one.
The .pkg is stapled, which is the one thing it does that the archive
cannot: its ticket travels inside the file, so a first launch works on a machine
that is offline or behind a filtered network. Verify it before installing with:
pkgutil --check-signature vincent_*_darwin_universal.pkg
spctl --assess --type install -vv vincent_*_darwin_universal.pkg
com.apple.provenance is unrelated — macOS adds it to everything and it does
not block execution.
Directories
macOS is the one platform where config and data are nested under the same root:
| Purpose | Location |
|---|---|
| Config | ~/Library/Application Support/vincent/ |
| Data | ~/Library/Application Support/vincent/data/ |
~/Library/Application Support/vincent/config.yaml # 0600, dir 0700
~/Library/Application Support/vincent/workflows/*.yaml
~/Library/Application Support/vincent/data/vincent.db
~/Library/Application Support/vincent/data/token # 0600
~/Library/Application Support/vincent/data/daemon.json
~/Library/Application Support/vincent/data/logs/daemon.log
~/Library/Application Support/vincent/data/worktrees/{task_id}/
~/Library/Application Support/vincent/data/transcripts/{task_id}/
Note the space in the path when scripting — quote it, or use
~/Library/Application\ Support/vincent. Both directories are overridable with
VINCENT_CONFIG_DIR and VINCENT_DATA_DIR; see
Files and directories.
Running at login
vincent service install
vincent service status
That writes a LaunchAgent to ~/Library/LaunchAgents — a per-user agent,
never a root LaunchDaemon, and no elevation is required. The OS user is
vincent’s trust boundary: an agent gets your privileges, your agent-CLI logins
and your git identity, and nothing more.
KeepAlive is conditional on a non-clean exit. A daemon that exits 0 was
asked to stop, and relaunching it would make vincent daemon stop impossible.
The agent starts at login, which is the same promise the Linux and Windows backends make.
The PATH problem
This is the macOS-specific gotcha, and it is worth understanding rather than just working around.
launchd hands a service a minimal PATH — /usr/bin:/bin:/usr/sbin:/sbin.
Every agent CLI installs outside it: Homebrew (/opt/homebrew/bin on Apple
silicon, /usr/local/bin on Intel), an npm prefix, an nvm shim directory,
~/.local/bin.
Left alone, an installed service therefore resolves no agent CLI at all, while the same daemon started by hand finds every one — the daemon runs, the TUI lists every adapter as missing, and nothing in either says why.
So vincent service install captures the PATH of the shell that ran it,
along with the config and data directories, and writes them into the plist. The
shell you install from has, by construction, the PATH that works.
Two consequences:
- It goes stale. Install an agent CLI somewhere new and run
vincent service installagain to recapture. That is the same “reinstall to recapture” contract the directories have. -
It is not the only answer.
agents.<name>.pathinconfig.yamlis absolute and never consultsPATH:agents: claude: { path: "/opt/homebrew/bin/claude" }
Verify with vincent daemon status or the TUI’s daemon view: if the adapter list
is empty under a service that is running, this is why.
Terminal notes
- Native text selection needs the TUI’s mouse handling off: press
M, or hold ⇧ while dragging. Cmd+Vpastes; it arrives as a bracketed paste and lands in the focused field with no key involved.$EDITORis honored for edit-and-retry and description editing. Use something that runs in the terminal and blocks until you close it —vim,nano, orcode --wait.- Everything on this platform behaves the same as Linux, including
restrictedpermission mode for all three adapters.