← Home / Imperator FreeGames

Imperator FreeGames

Polls a feed of games that are currently free to keep, notifies you when a new one shows up, and lists them all in a menu bar panel.

MenuBar AppMIT Licensev1.1.1Updated 2026-09-30

README.md

// Overview

A macOS menu bar watcher for game giveaways. It polls a public feed of games that are currently free to keep on Steam, Epic and GOG, notifies you when a new one shows up, and lists them all in a menu bar panel.

// Install

Download the latest zip from Releases, unzip, and move Imperator FreeGames.app to /Applications.

The app is signed with a self-signed certificate and is not notarized, so Gatekeeper blocks the first launch. Right-click the app and choose Open, or clear the quarantine flag:

xattr -dr com.apple.quarantine "/Applications/Imperator FreeGames.app"

Requires macOS 13 or later, Apple silicon. Built and tested on macOS 27 only — older versions are expected to work but have not been verified.

Building needs Swift 6.4 or later, because Package.swift declares swift-tools-version:6.4. That is a build requirement only; the app itself still runs on macOS 13.

Install at your own risk. The app is not notarized and carries no Apple Developer signature, so macOS cannot vouch for it. It is provided as is, with no warranty, under the MIT license.

// Permissions

No Accessibility, Input Monitoring, or Automation grants. The app declares no NSUsage keys and reads nothing on your machine.

Two system integrations:

IntegrationWhat it does
NotificationsOn first launch the app asks for notification permission through UNUserNotificationCenter. Decline it and everything still works — you just lose the alerts and keep the badge dot.
Open at LoginThe footer toggle calls SMAppService.mainApp.register(), which adds the app to Login Items in System Settings. Turning it off unregisters it.

Network access is one outbound HTTPS request every 30 minutes to https://www.goranimperator.com/data/free-games.json. Nothing is sent — no identifiers, no telemetry, no account. Clicking a game opens its store page in your default browser.

// Use

Click the menu bar icon to open the panel. Games are grouped by platform with a count per section; each row shows the title, the regular price it was before the giveaway, release year, developer and a short description. Click a row to open the store page.

A red dot on the menu bar icon means something new arrived since you last looked. Opening the panel clears it, and the new titles keep a red NEW pill until then.

The panel is drawn by the app, in MenuBarPanel.swift, rather than by NSPopover, whose radius cannot be set and never matches the one macOS 27 draws in the menu bar. It carries the system's .popover material with a 17.5pt corner, the same surface every Imperator menu bar app draws, with no arrow and no open or close animation.

The footer holds the controls:

ControlWhat it does
Open at LoginRegister or unregister the login item
WebsiteOpen the full free-games page in a browser
AboutVersion, build and copyright panel
QuitTerminate the app

The refresh arrow in the header forces a fetch instead of waiting for the next 30-minute tick.

State lives in ~/Library/Application Support/Imperator FreeGames/state.json: the IDs already seen, capped at the 50 most recent per platform. The first fetch after a fresh install seeds that list silently, so installing the app does not fire a notification for every game already on offer.

// Build from source

make install

Builds release, bundles, codesigns, installs to /Applications, and launches. Other targets:

make run
make clean

Signing uses the self-signed Imperator Dev identity by default. Override it:

make build CODESIGN_IDENTITY=-

Ad-hoc signing (-) mints a new code hash on every build, which drops the login-item registration on update. Fine for local iteration, wrong for a release.

AppKit decides which generation of a control to draw from the SDK field in the binary's LC_BUILD_VERSION, not from the macOS it runs on, and SwiftPM fills that field from platforms: rather than from the SDK it compiled against. The Makefile stamps sdk 27.0 through a linker flag instead of raising platforms:, so the app draws current controls without locking out anything below macOS 13.

// Release

Build a zip without touching git or the remote:

make dist VERSION=1.0.0

Cut a full release — bumps Info.plist, commits, tags v1.0.0, pushes, and publishes a GitHub release with the zip attached:

make release VERSION=1.0.0

Requires the GitHub CLI (brew install gh, then gh auth login). The working tree must be clean. Tags are plain semver (v1.0.0); the release title carries the app name. CFBundleVersion is set from git rev-list --count HEAD and is never edited by hand.

// Implementation note

A SwiftPM executable with no dependencies. LSUIElement is true, so there is no Dock icon and no menu — the status item is the entire interface. Because SwiftPM does not compile asset catalogs, the panel and menu bar icons are inline SVG strings decoded through NSImage(data:) with isTemplate = true, so they follow the system appearance.