// docs/guides/running-at-login.md docs online

Running at login

vincent service install registers the daemon with your operating system so it starts at login and survives a reboot. Without it the daemon lives only as long as something started it.

vincent service install     # register and start
vincent service status      # installed? running?
vincent service uninstall   # stop and remove

It always runs as you

On every platform, the service is a per-user registration and needs no elevation to install, uninstall or query.

That is not a convenience choice. The OS user is vincent’s trust boundary: an agent gets your privileges, your agent-CLI logins and your git identity, and nothing more. A machine-wide service would run agents as a system account — with more privilege and none of your credentials, which is the worst of both.

What gets installed

Platform Mechanism Where
macOS LaunchAgent ~/Library/LaunchAgents
Linux systemd user unit ~/.config/systemd/user
Windows Scheduled Task, triggered at logon Task Scheduler, named vincent

Restart policy is deliberately conditional on a non-clean exit — launchd’s KeepAlive on failure, systemd’s Restart=on-failure, the Scheduled Task’s RestartOnFailure. A daemon that exited 0 was asked to stop, and relaunching it would make vincent daemon stop impossible.

The registration starts the daemon at logon, not at boot, on all three platforms — that is what a LaunchAgent does, what a systemd user unit without lingering does, and now what the Windows task does. Running with nobody logged in requires a service account with a stored password, which is a different feature and not one vincent has.

What is captured at install time

A service does not inherit the shell that installed it, so the installer writes the values in effect into the unit.

The directories, everywhere

VINCENT_CONFIG_DIR and VINCENT_DATA_DIR overrides would otherwise apply to your CLI and not to the service, and the two would silently use different databases. So the resolved directories travel with the registration — as environment variables in the plist and the unit, and as --config-dir / --data-dir arguments on Windows, where a scheduled task’s action has no environment at all.

PATH too, on macOS and Linux

A service manager supplies its own minimal PATH. launchd’s is /usr/bin:/bin:/usr/sbin:/sbin; a systemd user manager’s is barely wider. Every agent CLI installs outside it — Homebrew, 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 of them: the daemon runs, the TUI lists every adapter as missing, and nothing in either says why. The shell running service install has, by construction, the PATH that works, so that is what gets captured.

Two consequences, both deliberate:

  • The captured PATH goes stale. Install a CLI somewhere new and you want vincent service install again to recapture it — the same “reinstall to recapture” contract the directories already have.
  • Windows does not capture it. The task runs in your logon session and therefore already has your own PATH, including %APPDATA%\npm. Freezing a copy would replace a live correct value with a stale one.

On every platform the standing answer to an agent that will not resolve is the agents.<name>.path config key, which is absolute and never consults PATH.

Windows specifics

The Windows backend is a Scheduled Task, not a Windows Service. It appears in Task Scheduler as vincent and never in services.msc. It runs with no visible window, so vincent service status and vincent daemon status are how you check on it.

Four scheduler defaults are overridden, because each one would otherwise stop a long-running daemon: the three-day execution time limit is removed, both battery settings are off, and stop-on-idle-end is off.

Install from an ordinary prompt

A task registered by an elevated process is owned by BUILTIN\Administrators, and the ACL Task Scheduler writes leaves your own account read-only — so a later install or uninstall from an ordinary prompt fails with ERROR: Access is denied, naming neither the owner nor the remedy.

Installed unelevated, CREATOR OWNER grants your account full control and every later install and uninstall needs no elevation. Both commands detect the denied case and tell you the elevated uninstall that clears it.

The console flash

The daemon releases its console at startup when it owns it, which is what keeps a terminal window from sitting on your desktop after every logon — and what stops that window’s close button from killing the daemon. Passed by hand in a terminal the flag does nothing, rather than taking your own shell down.

One brief flash between the scheduler creating the process and the daemon reaching that call is what remains. It is cosmetic.

Upgrading from a pre-Scheduled-Task version

Older versions installed a Windows Service that ran as LocalSystem — which is why your TUI kept starting a daemon of its own: the service resolved %LOCALAPPDATA% to the SYSTEM profile and wrote its database somewhere your user account never looks.

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

Linux and logout

The user unit starts at login and stops at logout unless lingering is enabled:

loginctl enable-linger "$USER"

The installer attempts this itself and, if it cannot, prints the exact command for you to run. Either way the service is installed and running — this is a warning, not a failed install. Without lingering, the daemon still survives everything except logging out entirely.

Reinstalling

vincent service install is idempotent: run it again to re-register with current values. Do that after:

  • upgrading vincent, if the binary moved
  • installing an agent CLI somewhere new (macOS/Linux — PATH capture)
  • changing VINCENT_CONFIG_DIR or VINCENT_DATA_DIR

Verifying it worked

vincent service status     # installed / running, per the OS's own view
vincent daemon status      # 0 healthy, 1 not running, 2 unresponsive
vincent                    # the TUI's daemon view lists resolved adapters

The check that actually matters is the adapter list: a service that runs but resolves no agents is the failure mode this page exists to prevent. If that is what you see, reinstall from a shell where which claude works.

Log out and back in — or reboot — and run the same three commands. That is the whole acceptance test.


See also