# Automation: Triggers & Scheduling
URGithub is driven by triggers. Every trigger — startup, shutdown, a timer, a file change, a button — enters the exact same pipeline. **Rule 3:** every trigger runs `runner.run_trigger()`, which executes the identical gate chain and pipeline.
```mermaid
flowchart LR
OS[Operating-system scheduler
Task Scheduler · cron · systemd · launchd] --> T[URGithub trigger] --> E[Same URGithub engine
full pipeline]
```
The scheduling mechanism changes; the repository-processing engine stays the same.
## Trigger types
| Trigger | Config key | Notes |
|---|---|---|
| Login / startup | `triggers.startup` | Runs when you log in (full pipeline) |
| Scheduled repeat | `triggers.every_hours` / `every_minutes` | e.g. `3` = every 3 hours; `every_minutes` wins when > 0; epoch-aligned boundaries |
| Daily at a time | `triggers.at_time` | e.g. `"18:00"`; rolls to tomorrow if the time has passed |
| File change | `triggers.file_change` | Watches `repos in github\`; `.git` internals ignored |
| Shutdown quick-push | `triggers.shutdown` | Windows only — push pending work before shutdown |
| Manual | `triggers.manual` | Control Center button / CLI |
| Manual scan / sync | — | Control panel buttons; interactive runs open the report |
| Event hook | *(roadmap)* | Webhook / email — same entry point |
## Windows — Task Scheduler
The `--schedule` family installs and manages everything through Windows Task Scheduler:
```bash
python urgithub.py --schedule install
python urgithub.py --schedule status
python urgithub.py --schedule uninstall
```
It creates these tasks (all pointing at absolute `python.exe` + script paths):
| Task | Schedule |
|---|---|
| `URGithub-startup` | At user logon |
| `URGithub-scheduled` | Every N hours / minutes, or daily at `at_time` |
| `URGithub-shutdown` | Event-triggered on shutdown/restart/logoff (EventID 1074, provider User32), 10 s delay, runs as SYSTEM, network-only, 2-minute execution cap |
It also **deploys the full launcher set** (`start/scan/sync/shutdown/schedule/manual.bat`) into `\urgithub\Run\`.
```mermaid
flowchart TD
W[Windows logon] --> S[URGithub startup trigger]
T[Timer] --> SCH[URGithub scheduled trigger]
E[Windows shutdown event
EventID 1074] --> Q[URGithub quick-push trigger]
S --> E1[Single runner]
SCH --> E1
Q --> E1
```
> Creating the SYSTEM-level shutdown task may require an elevated (admin) prompt. `--setup-all` and the wizard retry it with a UAC prompt automatically.
### Resident scheduler (Windows)
Running URGithub from the system tray (`--tray` or the Control Center) starts a resident scheduler that repeats the run interval *while the app is running*, complementing the Task Scheduler tasks.
### Resident scheduler (Linux / macOS)
URGithub is a regular process. Run it from the terminal, or supervise it so it stays alive and the resident scheduler keeps repeating at your configured interval.
## Linux — cron / systemd
Add a cron entry using the absolute path to the CLI:
```bash
crontab -e
```
```cron
# every 3 hours
0 */3 * * * cd /home/you/push-to-github && /usr/bin/python3 urgithub.py --run scheduled
# at 18:00 daily
0 18 * * * cd /home/you/push-to-github && /usr/bin/python3 urgithub.py --run scheduled
```
Alternative: a `systemd` timer unit calling the same `--run scheduled` entry point.
## macOS — launchd / cron
Use a `launchd` plist (the `StartInterval` key repeats every N seconds) or plain cron, both calling `python3 urgithub.py --run scheduled` with the absolute path to `urgithub.py`.
## Shutdown quick-push
> **Windows only.** During shutdown, URGithub pushes pending changes within a short time budget (`shutdown.timeout_seconds`, default 30s). It never delays the machine indefinitely and does not open the report (`shutdown.open_report`, default off). Shutdown is *not* a full sync — it is intentionally constrained.
## File watcher
```bash
python urgithub.py --watch
```
The watcher polls `repos in github\` every 10 seconds, waits for 30 seconds of quiet (debounce), then fires the `file_change` trigger. Git's internal `.git` directory is ignored so git bookkeeping never triggers spurious runs. The watcher does **not** implement a separate sync engine — it triggers the same single pipeline.
```mermaid
flowchart LR
F[File change] --> T[Trigger] --> R[runner] --> D[Discover] --> S[Scan] --> V[Validate] --> Y[Sync] --> P[Report]
```
## Control Center
Launch with `python urgithub.py` (no arguments) or `python urgithub.py --tray`. The GUI provides Dashboard / Repositories / Schedule / Settings / Logs / Help, with **Scan now** / **Sync now** buttons, schedule status, a resident timer and a streaming log — everything runs in background threads so the UI never freezes.
## Best practices
- Use absolute paths in cron / launchd entries — scheduled runs have no terminal PATH.
- Keep `every_minutes` at `0` unless you need sub-hour runs.
- After any `triggers.*` change, reinstall the scheduler: `--schedule install`, then `--schedule status`.
- All triggers share one pipeline and one report — scheduled runs are never "weaker" than manual ones.
Next: [Security](security.md) — what the safety model blocks and why.