Laptop client guide¶
The winner client sends a developer's coding-agent sessions to their
team's Winner AI deployment, from the repos they choose and no others. This
page takes a developer from nothing to a laptop that pushes, on macOS or on
Ubuntu or Debian: install, sign in, choose the repos, and what to expect
afterwards. Client reference holds the detail behind each
step.
Supported systems¶
| System | Versions | Architectures |
|---|---|---|
| macOS | 13 (Ventura) or later | Apple Silicon and Intel (one universal binary) |
| Ubuntu | 20.04 or later | amd64 and arm64 |
| Debian | 11 or later; 12 on amd64 is the one validated | amd64 and arm64 |
On Linux the installer refuses, before downloading anything, a machine
whose C library is older than glibc 2.28 (the client's session collector,
agentsview, needs it, and its project publishes no musl or static build),
so Ubuntu 18.04 and Alpine are refused. It also needs ssh-keygen from OpenSSH 8.1 or later (the
openssh-client package; ssh -V shows the version) to check the release
signature. Requirements has the rest.
winner login and winner repos list the laptop's repos with git 2.36 or
newer (git --version shows yours). The stock git of Ubuntu 20.04 and 22.04
and Debian 11 is older, and a Mac without the Command Line Tools has none.
Those systems stay supported, so the installer warns and installs anyway;
until git is updated, the first login on a newly enrolled laptop with coding
sessions in a project folder says, for example,
"Could not list this laptop's repos (git 2.25.1 found; listing repos needs
git 2.36 or newer), so none are chosen and nothing is sent."
Requirements says how to get git 2.36 or newer on
each system and what to run after.
Windows is not supported in this release: the installer stops with "Windows builds are not published yet."
Install on macOS¶
Open Terminal and run the installer your team's control plane serves.
Replace <control-plane-host> with the hostname your team's control plane
runs at; whoever deployed it can give you the line with it filled in. Left
as written the shell reads < and > as redirection and installs nothing.
curl -fsSL --proto '=https' --proto-redir '=https' https://<control-plane-host>/install.sh | bash
The two --proto flags keep the fetch on https from end to end: -L
follows redirects, and without them a redirect to plain http would pipe
unverified bytes straight into bash. A trial of the server serves plain
http on loopback, which those flags refuse; for one, the line is
curl -fsS --noproxy localhost http://localhost:4180/install.sh | bash,
run on the trial machine itself. Any other laptop first needs the tunnel in A trial from the
bundle, with port 4180 and the
trial's POSTGRES_PORT free on it (not held by a stack of its own).
It needs no sudo and no GitHub account. It installs winner, and
the session collector (agentsview) at the version the control plane runs
when the laptop has none, into ~/.local/bin. It checks winner against checksums signed with
the Winner AI release key, and the collector against its project's own
checksums, which no one signs (Requirements). It
records the control plane in ~/.agentsview/fleetview-control-url. If that
folder is not on your PATH it prints the export PATH=... line to run;
it ends by printing the winner login line to run next.
Run it in Terminal, not by downloading winner with a browser. A file a
browser downloads is quarantined, and macOS refuses to run it; curl sets
no such flag. If you did download it that way, clear the flag:
xattr -d com.apple.quarantine ~/.local/bin/winner
Running the installer again on a laptop that is already enrolled is safe: it replaces the binary and keeps the enrolment, the repo choice and the background push. Its "Next step" line can be ignored there.
What you see: the unsigned build¶
The macOS binary of this release is not signed with a Developer ID; that
comes in a later release. Gatekeeper does not stop it, because the
installer's download carries no quarantine flag. What you notice is the
name: after winner login, macOS shows a "Background Items Added"
notification named after the binary, "winner", rather than Winner AI.
The login installs three background items, listed under System Settings > General > Login Items > Allow in the Background:
| Item (launch agent label) | What it does |
|---|---|
com.getwinner.push |
The background push: sends the sessions of your chosen repos as they change |
com.getwinner.update |
The daily update: runs winner update at login and every day at noon |
dev.winner.reporter |
The hourly reporter: tells the control plane the names this laptop pushes under, and the start commit of recent sessions in your chosen repos; sends the name and state of each repo and applies the choices made on the web page |
Switching an item off there stops that job; switching off the push stops
sending. On the current release winner login does not ask macOS for
access to Desktop or Documents: the binary carries no signature macOS
checks, so sessions in those folders are recorded without a start commit.
A signed build changes this. It asks once, for the reporter:
Folder access on macOS says what that
reads. It asks only when a recent session ran in one of them, through a
fourth, one-shot launch agent, dev.winner.folder-access, that login
installs, runs and removes within the two minutes it waits for your answer;
it is not one of the standing items. Whether macOS also announces it with a
"Background Items Added" notification of its own has not been checked.
For IT: allowing the items with an MDM¶
The approved install path is the one above: each developer runs the curl
installer, which installs to ~/.local/bin with no sudo. An MDM can then
keep the three items on. A Managed Login Items policy (the
com.apple.servicemanagement payload; JumpCloud offers it for macOS 13 and
later) with three Label rules, one per label in the table above,
approves them, and once applied users cannot switch them off. The
one-shot dev.winner.folder-access job needs no rule: login removes it as
soon as the folder-access question is answered or times out. A single
Label Prefix rule cannot cover all three, because the reporter's label
starts with dev.winner. and the other two with com.getwinner..
Check also that no endpoint security or binary allow-listing tool blocks unsigned executables in users' home folders.
Untested: that a Label rule approves an unsigned item has not been tried on a JumpCloud-enrolled Mac. Until it has, check it on one Mac before rolling the policy out.
Install on Ubuntu or Debian¶
Run the same installer line as on macOS (Install on macOS),
in a terminal, with no sudo. It installs the static winner binary for your architecture, and
the collector when the machine has none, into ~/.local/bin, under the same
checksum checks as on macOS. On a default Ubuntu a new login
shell puts ~/.local/bin on PATH once it exists, but the shell you
installed from does not: run the export PATH=... line the installer
printed, or open a new shell, before winner login.
Login installs a systemd user unit and two user timers in
~/.config/systemd/user/ (or under XDG_CONFIG_HOME when you set it):
winner-push.service (the background push), winner-update.timer (the
daily update) and winner-reporter.timer (the hourly reporter).
Machines with no login session¶
The push and both timers belong to your login session, which a laptop gives
them. A machine you only reach over SSH starts no session at boot, so they
wait until you log in unless you let your user manager linger. That needs no
sudo on Ubuntu:
loginctl enable-linger "$USER"
Name the user: a bare loginctl enable-linger with no login session fails
with "No such device or address".
A Linux machine that does not run systemd (WSL without systemd=true, most
containers) gets no background push. Login warns that the push was not
installed, and prints crontab lines for the daily update and the hourly
reporter for you to add with crontab -e.
Sign in¶
winner login
--control-url https://<control-plane-host> is optional on a laptop the
installer set up: login uses the flag, then FLEETVIEW_CONTROL_URL, then
the control plane the installer recorded. Against a trial of the server it
is --control-url http://localhost:4180.
Login first checks this laptop's collector version against the control plane's (The collector version ceiling). It then prints a code and the full address of the control plane's approval page. Open that address in any browser, on this laptop or on another machine, sign in with your work account and approve the code. Nothing listens on the laptop for the answer.
On a control plane that serves its own sign-in, the laptop talks only to the control plane; your browser is what visits your company's identity provider. A control plane without its own sign-in is the exception (What the laptop sends, and where).
Login then installs the background push and the two scheduled jobs, and,
on a laptop with no repo choice yet, asks which repos to send (next
section). winner login --no-service enrolls without installing any of
them.
Choose which repos send¶
A laptop sends the sessions of the repos its developer chose, and nothing is chosen for you. A laptop that already has a choice keeps it, and login says "Repo selection kept: ..." without asking. Otherwise, at a terminal, login lists the repos this laptop's coding sessions ran in, with none ticked:
- numbers and ranges tick and untick rows:
1 3 5-7; aticks all the repos shown except shared or separated names,nnone of them;/textshows only the repos matchingtext,/shows all again;- Enter goes on to one last question, what happens to a repo found later
(
1ask,2block; Enter keeps the one shown), and the choice is saved after it;qquits without saving, and nothing is sent. Ending the input at either question quits the same way.
A login with no terminal chooses nothing and says so: "No terminal to ask
on, so no repos are chosen and nothing is sent. Choose them with: winner
repos pick". On a fresh machine where no coding agent has run yet there is
nothing to list: "agentsview lists no repos on this laptop yet; nothing is
sent. Choose them later with: winner repos pick". Use your coding agent
once in a repo, then run winner repos pick. Where the collector or git cannot
list the repos, login says "Could not list this laptop's repos (...), so none
are chosen and nothing is sent. Choose them with: winner repos pick", with
the reason in the brackets. Where a saved choice cannot be read, login says
so, then "Choose your repos again with: winner repos pick".
The list comes from the collector, which the background push starts, so
winner login --no-service usually cannot ask: unless a collector you
started yourself is running, it ends with "agentsview is not running yet, so
no repos are chosen and nothing is sent. Once it runs, choose them with:
winner repos pick".
To see or change the choice later:
winner repos # every repo, grouped by what happens to it
winner repos list web # only those whose name, path or remote holds "web"
winner repos pick # the same list as at login, from your current choice
winner repos allow web-app # send it, earlier sessions included
winner repos allow --all # send every repo listed, except shared or separated names
winner repos block web-app # stop sending its new sessions; those already sent stay
winner repos block --all # stop sending any repo's new sessions
winner repos separate api # give each checkout behind a shared name its own name
winner repos mode ask # or block: what happens to a repo found later
winner repos apply # re-apply ~/.agentsview/fleetview-repos.json after a hand edit
winner repos help # the commands, then what is sent and what cannot be withdrawn
winner repos list reads from the collector, so it needs the collector
running, as it is while the background push runs.
The first time it starts, the collector reads every coding session already on
the laptop before it answers, which takes a while on a long history; the
background push waits for that and pushes once it ends. Until then
winner repos says agentsview is still starting and how far it has got, as
the collector reports it (for example "initial sync: 300/321 sessions (93%) ยท
5120 messages"); run
it again once it finishes.
winner repos allow --all leaves out a name that several checkouts share
and a name that was separated, and prints "Skipped ..." for each, saying
why; allow those by name.
A repo first seen after you chose is handled by the mode:
ask, the default: "New repos wait for you until you allow them; winner repos lists them as waiting."block: "New repos are blocked and nothing asks you about them; winner repos still lists them."
What the client says of the repos you do not choose is: "Sessions from repos you don't choose stay on this laptop, unless one of them carries the name of a repo you chose." A Cursor session is named after its folder, not its repository root, so a folder that reads as a chosen repo's name is sent under it.
What was sent stays. Blocking a repo, or unticking it, stops its new sessions only: "Sessions already sent stay with your team." Nothing the client does deletes what was sent, and deleting sent sessions is not in this release. Allowing a repo works the other way: it sends that repo's earlier sessions too, not only new ones.
A repo's name is recorded from its folder name: the basename of
the git root, with every - read as _ and case kept, so web-app and
web_app are one repo. When two checkouts share a name, allowing it would
send both, so the list and the picker never allow it and name the
checkouts. winner repos separate <repo>, or winner repos allow <repo>
at a terminal, asks for a new name for each checkout, suggesting
owner/repo from its remote, before anything is sent; the new name is what
your team sees. A shared name that was already sent cannot be separated:
what was sent stays merged under it.
No winner command renames a repo already sent: the sessions sent stay
under that name, because a rename would make the next push delete them
from your team's server. winner repos rename <repo> only says so and
changes nothing. A rename in the collector's own interface is not covered;
see limit 3 below. A separation that stops partway keeps a folder rule
under the name you chose for a checkout once that name was sent, or when
the record of sent repos cannot be read, and says which and why: removing
it would move that folder's sessions out of the name as surely as making
one, so its new sessions go under that name. Blocking a repo
already sent always works, and what was sent stays.
The collector's search index reads every session on the laptop, chosen or not,
and sends its text to the embeddings endpoint its config names. By default
that is the laptop's own localhost:11434, so nothing leaves the laptop,
and no vector of a repo you did not choose reaches your team's database. If
the endpoint is set to another host, the text of unchosen repos goes there
too: the picker and winner repos help then name that host. The index
cannot be switched off for one repo, only for the whole laptop.
The choice is kept on the laptop in ~/.agentsview/fleetview-repos.json,
and only the laptop writes it; the names of its repos, unchosen ones
included, do leave it (Choices made on the web page).
A reinstall that removes ~/.agentsview removes it, and nothing is sent
until repos are chosen again.
A laptop enrolled before repo selection existed sent every repo. Its next
winner login, or its first winner update after the client that added
selection is installed (the daily update runs it), allows every repo
the collector lists then and records them as chosen, so it keeps sending what
it sent and repos found from then on wait for you. If that cannot be done
safely, the laptop keeps sending every repo, says why, and checks again at
the next update or login; until then winner repos changes nothing and says
so. The reasons: agentsview is not on PATH; it has not finished a push
since it was installed or updated, or no push log shows one; its names
cannot all be read, or its answers cannot be used as they are; or it holds
sessions under a name the list would leave out. winner update tries only
on a run that changed nothing: a run that replaced winner or the collector,
or was due to, has not pushed with the new version yet.
A laptop with no background push, one enrolled with --no-service, is
checked only after a winner login without --no-service.
Choices made on the web page¶
The web page is Your repos, at https://<control-plane-host>/repos,
linked from a Member's Home page on the server.
On a laptop holding a laptop pass, with the background push installed, the
hourly reporter also sends the control plane the name of every repo
the collector lists here, chosen or not, each with its state: allowed, blocked,
waiting for you, or shared by several checkouts. Nothing else about a repo
leaves: no remote, no file name, and no path beyond what the name itself
holds, which for Cursor is built from the folder's path. The control plane
answers with the choices you made on the web page, and the laptop applies
each one itself,
exactly as winner repos allow or winner repos block would, stopping the
push, writing the list and starting it again; the control plane never writes
the list. A choice takes effect at the reporter's next run, which is within
the hour on macOS and on Linux (winner-reporter.timer), later while the
laptop sleeps or while the collector is not running here, and the page shows it
as pending until then.
A choice is refused, with its reason sent back, for a name several
checkouts share, a name that was separated, a name this laptop does not
have, or a shared name this laptop has already sent. The reporter opens no
session folder and runs no git to list them, so each folder a repo's
sessions ran in counts as a checkout of its own: a repo whose sessions also
ran in a subfolder or a linked worktree shows as shared on the page and is
refused there, and winner repos allow is the way to allow it.
Each choice is applied once: a change you make with winner repos after
the laptop took a choice wins over it, and the ids of the choices applied
are kept in ~/.agentsview/fleetview-repo-choices.json until the control
plane stops sending them. A choice carries no time, so a change you made
before the laptop took it does not win: an allow clicked on the page and
then blocked with winner repos block before the reporter's next run is
still applied, and that repo's earlier sessions are sent, which cannot be
withdrawn. Blocking it on the page replaces an allow still pending. A push
stopped with winner push stop stays stopped and takes the new list at
winner push start. A control plane that cannot be reached, or answers
anything but the list of choices, changes nothing here, and a choice the
list could not be written for, or that a push still running on the old
list would not follow, because it did not stop or the collector's own push
service could not be removed, stays pending; the next run tries again.
Until a run, or a winner repos change, sees every push on the new list,
~/.agentsview/fleetview-repo-choices-old-list marks the laptop, and each
run stops and restarts the push to try again. winner repos apply says
what held it: a push that did not stop (winner push status), or
the collector's own push service, which goes once agentsview is on PATH or
after agentsview pg service uninstall.
A laptop enrolled with --no-service, one still on a sign-in token from
before the laptop pass, or a Linux machine without systemd collects nothing
from the page: use winner repos there. Nor does a laptop enrolled before
repo selection that still sends every repo: it sends no list until
winner update or winner login has kept the repos it sends, and the
page's choices wait until then.
Known limits of this release¶
None of these is fixed in this release.
- Cursor spend is missing from laptops. No Cursor usage rows leave a laptop whose push is filtered, and every laptop with repo selection filters, so the Dashboard has no Cursor spend from laptops.
- A later checkout under an allowed name is sent. A second clone of an allowed repo, a linked worktree made later, or a Cursor folder that reads as an allowed name, is sent under that name without asking.
- A rename in the collector's own interface deletes stored sessions. Renaming a project in the collector's own interface (the agentsview app or its local web page) makes the next push delete the rows stored under the old name on your team's server.
- The laptop's database login can delete stored rows. Its credentials
are in
~/.agentsview/config.toml, and with them plain SQL can delete that laptop's rows on the server. Backups are the answer (Back up, restore and uninstall); narrowing it is being looked at for a later release.
Not yet tested, and so a known limit: a long time off the VPN followed by the catch-up.
What the laptop sends, and where¶
A laptop contacts its own deployment and nothing else of Winner AI's:
- the control plane, over https: the installer and the
winnerbinary, the configurationwinner loginreads, the sign-in and enrolment, the hourly report (with the name and state of each repo, Choices made on the web page), and the report of a failedwinner loginorwinner update(Whenwinnerfails); - the deployment's Postgres, on 5432, over TLS the laptop verifies
against the system trust store (
sslmode=verify-full): every push of session data goes there.
On a control plane that serves its own sign-in, the laptop never contacts
the identity provider; your browser does, while you sign in. On a control
plane without its own sign-in (its configuration names an Auth0 tenant
instead), the laptop itself does: winner login runs Auth0's device flow
from the laptop, and the hourly reporter refreshes its token at the Auth0
tenant. So does the reporter of a laptop whose last winner login signed
in that way, until a winner login against its own sign-in. The embeddings endpoint stays on the laptop
(localhost:11434) unless its config names another host (above).
Two kinds of traffic carry no session data:
- github.com, and the
githubusercontent.comhost it redirects release downloads to, for the collector's own release (agentsview, unmodified), which the installer andwinner updatedownload; - raw.githubusercontent.com and openrouter.ai, where the collector refreshes its model prices. The collector offers no switch for that refresh.
The collector's anonymous usage ping and its check for a newer version of itself are
switched off: every service winner installs sets
AGENTSVIEW_TELEMETRY_ENABLED=0 and AGENTSVIEW_DISABLE_UPDATE_CHECK=1,
and the config enrolment writes sets disable_update_check = true. A
daemon you start yourself afterwards, from the agentsview desktop app or a
shell, carries your own environment instead.
On a private deployment¶
When your deployment answers only on a private network, the laptop pushes
only while it is on the VPN. Off it, pushes fail and the push keeps
retrying; sessions wait on the laptop and catch up about a
minute after the network returns, none lost. A network change in the
middle of a push, such as joining the VPN, can hold the next push back for
about two minutes, until the server's keepalive settings drop the old connection; winner push
status shows nothing wrong meanwhile. winner login, winner
update and the hourly report also wait for the VPN. Home shows a laptop
Stale after 24 hours without a push, so during a pilot connect to the VPN
at least once a day. A full-tunnel VPN works too, where the private
network's own internet access reaches the identity provider and the hosts
above: sign-in and updates then go through it. A Mac on a full-tunnel AWS
Client VPN has been tested and pushed every session over it.
A laptop off the VPN has the detail.
Day to day¶
winner push status # running or stopped, repeated push failures, and when it last wrote to its log
winner push logs -f # follow what it pushes (-n N for the last N lines; 50 by default)
winner push stop # stops it, across reboots too, and on macOS any running collector
winner push start # resumes
During an outage the push service itself keeps running, so status still says running, and adds that "the last N pushes failed" with the newest failure's reason once two or more pushes in a row have failed. No warning is not proof that pushes land: status reads only the failures the collector records.
A stop holds across reboots, but the next winner login re-enables the
push: run winner push stop again after a re-login if you want it off.
If you signed in before your coding agent had ever run on the laptop, your
first sessions can arrive up to 15 minutes late, until the push restarts (a
reboot, an update that changes a binary, or winner push stop and
start). After that a session arrives within about 30 seconds of changing.
The client updates itself daily at noon: on macOS also at each login, and a
noon the Mac slept through becomes one run when it wakes; on Linux a noon
the machine was off for becomes one run at its next start. winner update
runs the same thing by hand, bringing winner and the collector to the
versions the control plane runs, in either direction. It restarts the push
only when it replaced the collector, replaced the collector's own push service, or
rewrote a push service set up before the collector's opt-outs:
winner update --check # report what would change; install nothing
winner update # converge now
winner update --force # also replace a winner the installer did not place, or an agentsview whose version cannot be read
winner update and
Running on its own cover its rules and
logs. For support, winner diagnostics writes one file to read and attach
(Collecting diagnostics).
Uninstall¶
Uninstalling deletes nothing already sent: what the laptop pushed stays with your team.
On macOS (these steps have not been run end to end on a Mac yet):
winner push uninstall
launchctl bootout gui/$(id -u) ~/Library/LaunchAgents/com.getwinner.update.plist
launchctl bootout gui/$(id -u) ~/Library/LaunchAgents/dev.winner.reporter.plist
rm ~/Library/LaunchAgents/com.getwinner.update.plist ~/Library/LaunchAgents/dev.winner.reporter.plist
rm ~/.local/bin/winner
On Ubuntu or Debian:
winner push uninstall
systemctl --user disable --now winner-update.timer winner-reporter.timer
units="${XDG_CONFIG_HOME:-$HOME/.config}/systemd/user"
rm "$units/winner-update.timer" "$units/winner-update.service" \
"$units/winner-reporter.timer" "$units/winner-reporter.service"
systemctl --user daemon-reload
rm ~/.local/bin/winner
If FLEETVIEW_BIN_DIR named another folder at install, remove winner
from there instead of ~/.local/bin. On a machine without systemd, remove
the crontab lines login printed with crontab -e instead of the timers.
winner push uninstall removes only the background push, and keeps its
logs.
None of this ends the laptop's access on the server: its database login and its laptop pass stay valid there. Ask a manager to press Revoke beside the laptop on Admin, which ends both.
~/.agentsview/ holds your local session history beside Winner AI's files
and the laptop's database login (~/.agentsview/config.toml) and pass, so
removing it removes those credentials from the laptop; removing it, and
the collector (agentsview) itself, is your choice.