AgeKeeper Spies watches tracked AoE2 players and raises Windows toast
notifications when they enter or leave lobbies/games. It is designed to run
either interactively (agekeeper-spies) or headless at login via Windows
Scheduled Task.
- Real-time watchlist tracking for AoE2 player activity:
- Track when a player joins a lobby.
- Track when a player joins a match.
- Track when a player leaves either.
- Toast alerts with player avatar, map, civ, and lobby/game context.
- Scheduled task lifecycle commands for headless startup:
- Can be started upon Windows user logon.
- Built-in log tail mode for live process monitoring.
- Single-instance guard to prevent duplicate watcher processes.
- Windows (toast and scheduled task features are Windows-only).
- Python 3.11+.
- Network access for AoE2 API lookups and subscriptions.
pip install "agekeeper-spies @ git+https://github.com/DiscantX/AgeKeeper-Spies.git@main"Installed entrypoint:
agekeeper-spiesSpies reads tracked players from spies/watchlist.json.
If the file does not exist, Spies creates a template on first run.
Example:
[
{
"userName": "Hera",
"profileid": "199325",
"avatar_filepath": "spies/assets/default_avatar.png"
},
{
"profileid": "123456"
},
{
"userName": "TheViper"
}
]Rules:
-
Each item can be a full object, a profile ID string, or a profile ID number.
-
profileidanduserNamecan be supplied together or separately. -
Missing usernames are resolved from IDs.
-
Missing IDs are resolved from usernames.
-
Providing a known ID will guarantee an accurate result.
-
Providing a name may not produce an id, or it may produce an inaccurate one:
- In the case of no id produced, it could be due to the fact that the search occurs in the leaderboards, and if a player is not ranked in the leaderboard, they will not appear.
- An inaccurate id would be the result of multiple players having similar or the same names. The first search result is used.
-
avatar_filepathis optional; default avatar is used if missing/empty. It will be updated automatically with the profile's Steam avatar the first time it is encountered or changed.
agekeeper-spiesagekeeper-spies --tail-logsBase command:
agekeeper-spies [options]When no options are provided, Spies starts the watcher runtime.
| Argument | Type | Default | Description |
|---|---|---|---|
--tail-logs |
flag | false |
Tail the Spies log instead of starting the watcher process. |
--tail-lines |
int | 100 |
Print last N lines before follow mode starts. Must be >= 0. |
--no-follow |
flag | false |
With --tail-logs, print requested lines and exit. |
Examples:
agekeeper-spies --tail-logs
agekeeper-spies --tail-logs --tail-lines 250
agekeeper-spies --tail-logs --tail-lines 0 --no-followOnly one task action may be selected per command.
| Argument | Type | Default | Description |
|---|---|---|---|
--task-register |
flag | false |
Register/update task to start Spies at user logon. |
--task-deregister |
flag | false |
Remove the scheduled task. |
--task-status |
flag | false |
Show detailed task status. |
--task-start |
flag | false |
Request immediate task start. |
--task-stop |
flag | false |
Request task stop if running. |
--task-name |
string | AgeKeeper\Spies |
Task Scheduler name/path. |
--task-python |
string | pythonw.exe when available |
Python executable used when registering the task. |
Examples:
agekeeper-spies --task-register
agekeeper-spies --task-status
agekeeper-spies --task-start
agekeeper-spies --task-stop
agekeeper-spies --task-deregister
agekeeper-spies --task-register --task-name "AgeKeeper\\Spies-Dev"
agekeeper-spies --task-register --task-python "C:\\Python311\\pythonw.exe"Start watcher in foreground:
agekeeper-spiesRegister headless startup at login:
agekeeper-spies --task-registerStart scheduled task:
agekeeper-spies --task-startShow current scheduled task details:
agekeeper-spies --task-statusTail only the latest 50 lines and exit:
agekeeper-spies --tail-logs --tail-lines 50 --no-followFollow logs live:
agekeeper-spies --tail-logs --tail-lines 200Resolved log file path order:
AGEKEEPER_LOG_DIR/spies.logwhenAGEKEEPER_LOG_DIRis set.%ProgramData%\AgeKeeper\logs\spies.logwhen%ProgramData%exists.- Package fallback:
spies/logs/spies.log.
Log format:
YYYY-MM-DD HH:MM:SS | LEVEL | logger_name | message
Rotation policy:
- Max file size:
1,000,000bytes. - Backup files kept:
5.
- Spies enforces single-instance execution using a process lock.
- If a second instance starts, it logs a warning and exits.
- If watchlist is empty, runtime exits after printing guidance.
- You cannot combine multiple task actions in one command.
- Invalid task action combinations return exit code
2. --tail-linesmust be non-negative; negative values return exit code2.
1: task not found (--task-status,--task-start,--task-stop) or log file missing when tailing.2: invalid CLI usage (for example, multiple task actions or invalid--tail-linesvalue).- Other non-zero values may be returned directly from Windows
schtasks.
- Confirm you are on Windows.
- Confirm Spies is running:
agekeeper-spies --tail-logs. - Verify watchlist has valid players with resolvable IDs/usernames.
- Check Windows notification settings for app/system toast blocking.
- Check exact task path/name with:
agekeeper-spies --task-status --task-name "AgeKeeper\\Spies". - Verify the
--task-pythonpath is valid and accessible at login. - Confirm task history and last result in Task Scheduler UI.
- Use the same
--task-nameused during registration. - Include folder path segments if task is under a folder:
AgeKeeper\\Spies(default).
- Check network access and API availability.
- Start with explicit
profileidvalues to bypass username lookup dependency.
- Start Spies once to initialize logging.
- If using
AGEKEEPER_LOG_DIR, verify folder permissions and existence.
- Package entrypoint:
agekeeper-spies = spies.spies:main. - Watchlist module:
spies/watchlist.py. - CLI parser:
spies/cli.py. - Task registration helpers:
spies/task_registration.py. - Logging utilities:
spies/logging_utils.py. - Runtime depends on
agekeeper(lobby/shared/aoe2api modules).
