AEO Track
Source: github.com/psyduckler/aeo-skills Part of: AEO Skills Suite
The scheduling layer for AEO visibility tracking. One command per workspace, one schedule, no infrastructure.
Requirements
- Python 3.9+ (stdlib only)
- macOS (launchd) OR Linux (cron)
- An
aeo.config.jsonin the workspace directory (runaeo-initfirst) aeo-baselineinstalled somewhere this skill can find it
Usage
# Dry-run: see what would be installed
python3 scripts/track.py --install --schedule daily
# Actually install
python3 scripts/track.py --install --schedule daily --apply
# Custom schedule and time
python3 scripts/track.py --install --schedule weekly --hour 8 --apply
# Inspect current install
python3 scripts/track.py --status
# Remove
python3 scripts/track.py --remove --apply
Run from inside the workspace directory (the one containing aeo.config.json), or pass --workdir PATH.
How it works
Generates a wrapper script at
~/.aeo-track/<id>/run.shthat:cds into the workspace directory- Sources
.envfrom that directory if present (loadsGEMINI_API_KEY) - Runs
python3 /path/to/aeo-baseline/scripts/baseline.py --yes - Appends stdout/stderr to
aeo-data/aeo-track.log
Installs a scheduled job that invokes the wrapper:
- macOS →
~/Library/LaunchAgents/ai.skills.aeo-track.<id>.plist+launchctl load - Linux →
crontab -lline with a unique marker for safe removal
- macOS →
Records state at
~/.aeo-track/<id>/state.jsonso--statusand--removeknow what to do.
<id> is sha1(absolute_workdir)[:12] — same workspace → same ID. Different workspaces don't collide.
Options
| Option | Description |
|---|---|
--install |
(Default) Set up the schedule |
--remove |
Tear down the schedule |
--status |
Show install info for the workspace |
--workdir PATH |
Workspace directory (default: cwd) |
--baseline-script PATH |
Absolute path to baseline.py (auto-detected if omitted) |
--schedule SPEC |
daily (default) | weekly | hourly | 'every Nm' |
--hour N |
Hour-of-day for daily/weekly (default: 9) |
--minute N |
Minute (default: 0) |
--apply |
Actually install/remove (default is print-only) |
Schedule syntax
--schedule value |
macOS launchd | Linux cron |
|---|---|---|
daily |
StartCalendarInterval{Hour, Minute} |
<min> <hour> * * * |
weekly |
StartCalendarInterval{Weekday=1, Hour, Minute} |
<min> <hour> * * 1 (Monday) |
hourly |
StartCalendarInterval{Minute} |
<min> * * * * |
every 15m |
StartInterval=900 |
*/15 * * * * |
Setting up the API key
The wrapper script sources .env from the workspace dir if present. Put your API key there:
# In the workspace dir
cat > .env <<'EOF'
GEMINI_API_KEY=your_key_here
EOF
echo .env >> .gitignore
Both launchd and cron run with minimal shell environment by default, so the scheduled job won't see env vars from your interactive shell. The .env file is the bridge.
Inspect logs
After scheduled runs accumulate, check the log:
tail -f aeo-data/aeo-track.log
Each run produces a fresh evidence file in aeo-data/run_<timestamp>.json — same format as a manual aeo-baseline invocation.
Idempotency
- Re-installing (with
--apply) on the same workspace replaces the previous schedule. On macOS this unloads + reloads the plist; on Linux it strips matching lines fromcrontab -lbefore appending the new one. --remove --applyis safe to run even if nothing is installed.- State is per-workspace, so installing in multiple project directories doesn't collide.
Limitations (v0)
- Windows is not supported for
--apply. The dry-run still prints the wrapper script so you can wire it into Task Scheduler manually. - The wrapper runs with the user's environment, so cron-style limits on subprocess resource usage apply.
- No retry logic at the schedule layer — if a scheduled run fails, the next one tries fresh.
aeo-baselineitself retries failed API calls internally. --statusconfirms launchd has the job loaded; for cron it only checks the recorded state file (runcrontab -l | grep aeo-trackfor the live view).
Pairs With
- aeo-init — creates the
aeo.config.jsonthat this skill schedules - aeo-baseline — the script that actually runs on each tick
- aeo-report (coming) — reads the accumulated baselines and generates trend reports