- Go 43.4%
- Svelte 35%
- TypeScript 9.9%
- HTML 8.7%
- CSS 1.2%
- Other 1.8%
The plot carries five conventions — a circle is one read, the x axis is order and not the clock, the hatching is a run, a full-height rule is time nobody played, a dash is not an observation — and none of them were written down. The owner read the flat stretch before a step as a tournament taking that long to play, which is exactly what an unexplained convention gets you. A Key button in the panel head opens a native <dialog>: six rows, each drawing the mark itself beside the sentence, in the chart's own colours. The marks run louder than the plot does — a 0.14 hatch reads across a 360px plot and vanishes in a 28px swatch — so the legend states each mark clearly and the plot then says it quietly. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CQvJLmGGT78DUxX6njJnTT |
||
|---|---|---|
| .forgejo/workflows | ||
| cmd/yafst | ||
| docs | ||
| internal | ||
| packaging | ||
| reference/mint-node | ||
| web | ||
| .air.toml | ||
| .gitignore | ||
| CLAUDE.md | ||
| go.mod | ||
| go.sum | ||
| LICENSE | ||
| Makefile | ||
| README.md | ||
yafst
Yet Another Finals Stats Tracker. A ranked stats tracker for
THE FINALS that runs on your own machine. One static
binary reads your match data from the game's backend, keeps it in a local SQLite database
and serves a dashboard at http://127.0.0.1:8745.
If another program already holds that port, yafst takes the next free one
(up to ten ports on) and logs which; yafst status shows where it is running.
Set listen in the config or pass --listen to pin an exact address.
What it tracks
- Rank score, observed after every tournament: the change, the placement part and the hidden adjustment on top of it, your peak and low, and how far the next division is.
- Tournaments: bracket, every squad in it, your result and the prize board.
- Rounds: map, class and the kit you carried, kills, deaths, damage, cash, stage and result.
- Items and loadouts: which kits win, which weapon carries your kills, what the lobby queues.
- Career: seasons, scorecards, sponsors and challenges.
- Players: teammates you keep queueing with and squads you keep meeting.
Nothing is estimated. Rank score is never calculated; only what the game reports is stored, and thin samples are flagged as such.
![]() |
![]() |
![]() |
![]() |
How it works
yafst signs in to Steam the same way the game does and mints the token the game uses to talk to Embark's backend. It then polls the read endpoints for your own account only: the tournament you are in, your round stats, your rank, your inventory. It never writes anything to the backend, never joins parties and never automates play.
- No screen capture, no OCR, no overlay, nothing injected into the game.
- Everything stays on your machine:
$XDG_DATA_HOME/yafst/holds the database and tokens,$XDG_CONFIG_HOME/yafst/config.tomlthe settings. - Of other players only what the bracket shows is kept: name, rank, class, loadout.
- A Scramble player names switch in Settings replaces every name, yours included, with a made-up one for screenshots and streams (the screenshots above use it).
yafst is not affiliated with Embark Studios. It relies on the game's private API and can stop working after a game update.
Install
Every release ships the same static binary for Linux (x86_64 and aarch64) and Windows (x86_64):
- AppImage:
chmod +x yafst-*.AppImage && ./yafst-*.AppImage. Double-clicking runs the daemon; arguments pass through, e.g../yafst-*.AppImage status. - Arch Linux:
yay -S yafst-bin. The AUR package follows every release. - Tarball:
yafst-<tag>-linux-{amd64,arm64}.tar.gzwith the binary, desktop entry and icon.SHA256SUMScovers every file. - Windows:
yafst-<tag>-windows-amd64.zip. Unzip it anywhere and runyafst.exe: the dashboard opens in its own window and a tray icon appears. To start it at login, tick Start at login in the tray menu or runyafst.exe autostart enablefrom a terminal. The binary is not code-signed, so SmartScreen shows "Windows protected your PC" on first run: More info → Run anyway. CheckSHA256SUMSfirst if in doubt.
First run
yafst run
The dashboard opens in its own window (Chromium, Chrome, Brave, Vivaldi or Edge in app mode; otherwise your default browser). Go to Settings, scan the QR code with the Steam mobile app (or sign in with credentials and a Steam Guard code), and yafst starts polling. Play a ranked tournament and it appears on the overview as it happens.
Other commands: yafst status (every file yafst keeps, with sizes, and the largest tables),
yafst logs, yafst config init (write the default config), yafst autostart,
yafst auth rotate (reset the dashboard sign-in), yafst uninstall, yafst version.
Running in the background
yafst is meant to stay running while you play. Closing the dashboard window does not stop it: the tray icon keeps it going, and Quit in the tray menu ends it. To have it start with your session:
yafst autostart enable # start at login
yafst autostart status
yafst autostart disable
On Linux this writes ~/.config/autostart/dev.wolfhound.yafst.desktop (an XDG autostart
entry, honoured by every desktop; from an AppImage it points at the AppImage). Your
desktop's own startup settings can switch the entry off, and yafst respects that. On
Windows it sets a yafst value under HKCU\Software\Microsoft\Windows\CurrentVersion\Run,
which shows up under Startup apps in Task Manager. Both start yafst run --no-open, so
nothing pops up at login; the tray menu opens the dashboard when you want it. If you move
or rename the AppImage or yafst.exe, the entry is corrected the next time yafst runs.
yafst run --no-tray runs without the tray icon, for a terminal or a service.
On Windows, yafst.exe is a windowed program: subcommands print to the terminal that
started them, but the prompt comes back before the output does.
When something goes wrong
Open Settings → Logs and press Copy logs. That copies a report with the yafst version, file locations, poll status and the last 500 log lines, ready to paste into an issue. Tokens, account ids, Steam ids, e-mail and IP addresses and your home directory are removed before it leaves yafst.
If the dashboard will not open, the same report comes from the terminal:
yafst logs # log file location and its last lines
yafst logs -report # the full report, built from the log file if the daemon is down
The log file is ~/.local/state/yafst/yafst.log. It rotates at 5 MB and keeps three old
files. [log] level and [log] file in config.toml change what it records.
Where your data lives
Everything yafst keeps stays on your machine, readable only by your user.
yafst status prints the exact paths and sizes on your system.
| Path | What it holds |
|---|---|
~/.config/yafst/config.toml |
Settings. Optional: yafst runs on defaults without it. |
~/.local/share/yafst/yafst.sqlite |
The database: your rounds, tournaments, rank history and inventory, plus the name, rank, class and loadout of the players in your brackets. The -wal and -shm files next to it are part of it. |
~/.local/share/yafst/steam_refresh_token |
Your Steam sign-in. Treat it like a password. |
~/.local/share/yafst/embark_token.json |
The short-lived game token minted from that sign-in. |
~/.local/share/yafst/machineid.bin |
A random machine id Steam asks for at sign-in. |
~/.local/share/yafst/api_token |
The dashboard sign-in token (see Access control). |
~/.local/state/yafst/yafst.log |
The log file, redacted. |
~/.local/state/yafst/sessions.json |
Which browsers are signed in to the dashboard. |
XDG_CONFIG_HOME, XDG_DATA_HOME and XDG_STATE_HOME move these folders, and
data_dir in config.toml moves the data folder on its own.
The database holds only what the dashboard shows: parsed round, tournament and
progression stats, plus the last game-server response of a tournament still in
progress. When an update changes the database layout, yafst moves the old file to
yafst.sqlite.v<N>-<date>.bak and starts a new one. The three newest backups are kept.
Access control
The dashboard listens on loopback only, but loopback is shared by every user and
program on the machine, so it asks for a sign-in. yafst run creates a random token
in ~/.local/share/yafst/api_token (readable by your user only); the tray icon and
yafst run open the dashboard through /auth?t=<token>, which sets a session
cookie in that browser and never shows the token again. A browser without the
cookie sees a "sign in from the tray" page instead of the dashboard. Sessions
survive restarts and expire after a year unused.
Scripts send the token as a bearer header:
curl -H "Authorization: Bearer $(cat ~/.local/share/yafst/api_token)" http://127.0.0.1:8745/api/status
yafst auth rotate replaces the token and signs every browser out; restart yafst
afterwards if it is running, then open the dashboard from the tray again.
Back up
Stop yafst, then copy the data folder:
cp -a ~/.local/share/yafst ~/yafst-backup-$(date +%F)
To back up while yafst runs, let SQLite make the copy:
sqlite3 ~/.local/share/yafst/yafst.sqlite ".backup $HOME/yafst-$(date +%F).sqlite"
A copy of the data folder includes your Steam sign-in. Keep it private, or leave out
steam_refresh_token and sign in again after restoring.
Reset
- Sign out: use Sign out in Settings, or delete
steam_refresh_tokenandembark_token.json. Then remove yafst from the authorized devices in your Steam account's security settings. - Start your history over: stop yafst and delete
yafst.sqlite,yafst.sqlite-walandyafst.sqlite-shm. A new database is created on the next start. - Default settings: delete
config.toml.
Uninstall
The tray menu has an Uninstall item (with a confirmation), and the same runs from a terminal:
yafst uninstall # remove yafst and its files; keeps the match database
yafst uninstall --delete-db # also delete the database and its backups
It stops the daemon, turns off start-at-login, deletes the sign-in secrets (always,
including the Steam token) and removes the program for however it was installed
(pacman -R yafst-bin for the AUR package, otherwise the AppImage or the unpacked
binary). The match database is kept unless you pass --delete-db, so a reinstall picks
up where you left off. Anything it cannot do itself it prints for you to finish by hand.
To do it by hand instead: yafst autostart disable, remove the program (the package or
the AppImage), then rm -rf ~/.config/yafst ~/.local/share/yafst ~/.local/state/yafst.
Either way, revoke yafst's Steam sign-in as described under Reset.
Build from source
Needs Go 1.25 and bun.
cd web && bun install && bun run build && cd ..
go build -o yafst ./cmd/yafst
Minting an Embark token needs two launcher secrets that are not in the tree:
put YAFST_EMBARK_CLIENT_SECRET=... and YAFST_EMBARK_HMAC_KEY=... in a
gitignored .env at the repo root (make build bakes them in, make dev and a
plain go run read them from the environment). See docs/auth_key_derivation.md §3.
make dev runs the auto-reloading pair for development (Go daemon on :8745 via
air, Vite with hot reload on :5173). make check
runs the same gates as CI. make dist builds every release artifact into dist/.
Releasing
git tag v0.2.0-beta.1 && git push origin v0.2.0-beta.1
CI builds the tarballs, AppImages and the Windows zip, publishes the release with the
commits since the previous tag, then renders packaging/aur/yafst-bin/PKGBUILD.in, test-builds it and pushes
it to the AUR. Versions follow SemVer; a -beta.N suffix marks a
pre-release. CI needs three repository secrets: AUR_SSH_KEY to push the AUR package, and
YAFST_EMBARK_CLIENT_SECRET and YAFST_EMBARK_HMAC_KEY, which the build bakes into the
binaries (see docs/auth_key_derivation.md §3).
License
MIT.




