Yet Another Finals Stat Tracker https://discord.gg/M3Hbaebxub
  • Go 43.4%
  • Svelte 35%
  • TypeScript 9.9%
  • HTML 8.7%
  • CSS 1.2%
  • Other 1.8%
Find a file
Wolfhound bd001a06fd
All checks were successful
CI / go (push) Successful in 39s
Release / release (push) Successful in 40s
Release / aur (push) Successful in 25s
rs: a key that says how to read the chart
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
2026-09-13 19:19:45 -04:00
.forgejo/workflows Move the Embark launcher secrets out of the tree 2026-09-11 18:15:13 -04:00
cmd/yafst feat: support link, and the window closes with the daemon 2026-09-11 20:37:38 -04:00
docs ui-audit: close out the overview at 1280 and retake its shots 2026-09-13 08:31:06 -04:00
internal rounds: say the class on every row, and read it off the kit 2026-09-13 18:58:06 -04:00
packaging Move the Embark launcher secrets out of the tree 2026-09-11 18:15:13 -04:00
reference/mint-node docs: sanity sweep after the app-hardening and theme work 2026-09-11 18:37:14 -04:00
web rs: a key that says how to read the chart 2026-09-13 19:19:45 -04:00
.air.toml yafst v0.2.0-beta.3 2026-09-11 14:12:17 -04:00
.gitignore yafst v0.2.0-beta.3 2026-09-11 14:12:17 -04:00
CLAUDE.md fix: keep the dashboard to one app window 2026-09-11 18:59:28 -04:00
go.mod feat: tray icon, single instance, update checker, autostart, Windows 2026-09-11 16:03:33 -04:00
go.sum feat: tray icon, single instance, update checker, autostart, Windows 2026-09-11 16:03:33 -04:00
LICENSE yafst v0.2.0-beta.3 2026-09-11 14:12:17 -04:00
Makefile make: print a signed-in dashboard URL while developing 2026-09-11 23:26:04 -04:00
README.md docs: sanity sweep after the app-hardening and theme work 2026-09-11 18:37:14 -04:00

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.

Overview: rank score, tonight's form, recent rounds, teammates and tracked tournaments

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.

Rank score Tournament
Rounds Items

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.toml the 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.gz with the binary, desktop entry and icon. SHA256SUMS covers every file.
  • Windows: yafst-<tag>-windows-amd64.zip. Unzip it anywhere and run yafst.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 run yafst.exe autostart enable from a terminal. The binary is not code-signed, so SmartScreen shows "Windows protected your PC" on first run: More info → Run anyway. Check SHA256SUMS first 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_token and embark_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-wal and yafst.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.