// docs/platforms/windows.md docs online

vincent on Windows

Windows is a first-class platform: the full test suite and every acceptance gate run on it in CI alongside macOS and Linux. This page covers what is genuinely different.


Install

WinGet is the shortest system-managed path:

winget install --id lezli01.Vincent --exact

Or use Vincent’s Scoop bucket:

scoop bucket add vincent https://github.com/lezli01/scoop-bucket
scoop install vincent/vincent

Both support x86-64 and ARM64, install Git when it is missing, and consume the same release zip as the manual path. Stable releases update Scoop immediately; WinGet can lag while Microsoft reviews the catalog pull request. mise is also supported: mise use -g github:lezli01/vincent.

To install without a manager, unzip the release archive and put vincent.exe somewhere on your PATH:

Expand-Archive vincent_*_windows_amd64.zip -DestinationPath $env:LOCALAPPDATA\Programs\vincent
# add that directory to your user PATH, then reopen the terminal
vincent version

SmartScreen will prompt on first run“Windows protected your PC”More infoRun anyway. Releases carry cosign signatures, SHA-256 checksums and GitHub build attestations, but not Authenticode code signing, which is a recurring certificate cost this project does not take on. The prompt appears once per binary and can also appear for WinGet, Scoop, or mise: those channels verify the archive but do not add Authenticode signing.

Package-manager metadata moves on stable releases only. If a newly introduced channel has not received its first stable release, use mise or the archive.

Full detail, including how to verify a download: Installation.

Directories

Purpose Location
Config %APPDATA%\vincent\
Data %LOCALAPPDATA%\vincent\

So, concretely:

%APPDATA%\vincent\config.yaml
%APPDATA%\vincent\workflows\*.yaml
%LOCALAPPDATA%\vincent\vincent.db
%LOCALAPPDATA%\vincent\token
%LOCALAPPDATA%\vincent\daemon.json
%LOCALAPPDATA%\vincent\logs\daemon.log
%LOCALAPPDATA%\vincent\worktrees\{task_id}\
%LOCALAPPDATA%\vincent\transcripts\{task_id}\

The API token is protected by the per-user ACL that %LOCALAPPDATA% inherits, and config.yaml by the one %APPDATA% inherits; vincent writes no DACL of its own. On POSIX the equivalent is an explicit 0600 on both, re-tightened on every daemon start — which is also why vincent doctor never prints a permissions row here: a mode carries no access control on Windows.

Both can be overridden with VINCENT_CONFIG_DIR and VINCENT_DATA_DIR — see Files and directories.

The shell command steps use

command and check steps run through:

pwsh -NoProfile -Command "<rendered>"

falling back to powershell when PowerShell 7 is absent. Pin a different one per step with shell: sh | pwsh | cmd.

vincent makes no attempt to translate command steps between platforms. If a workflow is meant to run on Windows and on POSIX, write commands that work in both — && chaining is fine everywhere, test -f is not — or pin the shell and accept that the workflow is platform-specific.

A workflow that is platform-specific should say so with platforms:. A file declaring platforms: [posix] is listed here with status unsupported and is never offered by the new-task picker, instead of being offered and then failing at its first cat. The reverse works too: platforms: [windows] for a workflow built around PowerShell.

Paths in templates come from the daemon and are Windows paths; a command step that hard-codes / separators will not do what you expect.

Running at login

The Windows backend is a Scheduled Task, not a Windows Service. It shows up in Task Scheduler as vincent and never in services.msc.

vincent service install     # from an ORDINARY prompt — see below
vincent service status

Three things to know:

  1. Install unelevated. A task registered by an elevated process is owned by BUILTIN\Administrators and leaves your own account unable to replace or remove it — a later install or uninstall fails with ERROR: Access is denied. Installed from an ordinary prompt, CREATOR OWNER grants you full control and nothing ever needs elevation again. Both commands detect the denied case and print the fix.

  2. It runs with no visible window. The daemon releases its console at startup, which is what keeps a terminal from sitting on your desktop after every logon — and what stops that window’s close button from killing the daemon. Use vincent service status and vincent daemon status to check on it. A brief flash at logon is what remains, and it is cosmetic.

  3. PATH is not captured, unlike macOS and Linux. The task runs in your own logon session and therefore already has your PATH, including %APPDATA%\npm. Freezing a copy would replace a live correct value with a stale one.

The task starts at logon, not at boot. Running with nobody logged in needs a service account with a stored password, which vincent does not do.

Upgrading from a version that installed a Windows Service

Older versions registered a real Windows Service, which ran as LocalSystem — which is why your TUI kept starting a daemon of its own. LocalSystem resolves %LOCALAPPDATA% to C:\Windows\System32\config\systemprofile\, so the service’s database, daemon.json and worktrees were written somewhere your user account never looks, and full-auto agents ran as SYSTEM without your agent-CLI credentials, .gitconfig or PATH.

vincent service install detects and refuses to run alongside it. vincent service uninstall from an elevated prompt removes it — once, because a machine-wide service is machine-wide. Afterwards vincent service install needs no elevation again.

Restricted mode and cursor

This is the one place a vincent capability is genuinely platform-dependent, and it is stated rather than discovered.

A cursor step with permission_mode: restricted fails on Windows. cursor-agent --sandbox enabled exits 1 with “Sandbox mode is enabled but not available on this system. Sandbox requires macOS or Linux” before doing any work. vincent surfaces that as block reason restricted_unsupported, under the normal retry policy.

Falling back to --force was rejected outright: it would run full-auto a step that explicitly asked not to be, converting a safety choice into its opposite on exactly one OS — the failure mode a user would never think to check for.

claude and codex both restrict fine on Windows. If a workflow needs a restricted step and must run on Windows, use one of those for that step.

Terminal notes

  • Windows Terminal (the Windows 11 default) is what the TUI is exercised against. Older consoles work but render box-drawing and colors less well.
  • Native text selection needs the TUI’s mouse handling off: press M, or shift-drag.
  • Ctrl+Shift+V pastes; it arrives as a bracketed paste and lands in the focused field. ctrl+v is a fallback for terminals that pass the key through instead.
  • $EDITOR is honored for edit-and-retry and for description editing. Set it to something that runs in the terminal and exits when done — a GUI editor that forks immediately will look like it did nothing.

Known gaps

Thing Status
Cursor restricted mode Unavailable — the step fails, it never downgrades
Authenticode code signing Not done — SmartScreen prompts once
Boot-time start (no logon) Not supported — the task is logon-triggered
Windows Service backend Removed in favor of a Scheduled Task, deliberately

Everything else — the daemon, the API, the TUI, all three adapters, the scheduler, crash recovery, worktrees, transcripts, retention — behaves identically to the POSIX platforms, and CI proves it on every pull request.


See also