Repository navigation
Echo Schedule
Plugin updates on client sites go out in a maintenance window, often at night. rhythm echo schedule runs that window for every site on an agency hub: for each site in turn it takes a snapshot of what the site's actions send, runs the update, then compares. The results stay in the hub's store, where rhythm echo report --site makes the client's report from them. This page covers the window's syntax, running one now, what it prints and what the update command may see.
rhythm echo schedule "Tue 02:00" --store /srv/echo --after "wp plugin update --all" # every Tuesday at 02:00
rhythm echo schedule --now --store /srv/echo --after "wp plugin update --all" # one window, nowschedule talks to a running hub, with the hub's read token in its environment (the read_token_env of sites.yaml).
rhythm echo schedule --now --store /home/you/hub/store --after "touch /var/www/staging/wp-content/testbed-state/s01"client-a: snapshot before the update
client-a: touch /var/www/staging/wp-content/testbed-state/s01
client-a: compare with "pre-update"
client-a: Something broke: 2 broke, 0 new, 0 changed, 0 fixed.
(The "update" here breaks the test shop's contact form, as a plugin update that switched off the owner's notification would.) For each site in sites.yaml, in turn:
-
Snapshot: the site's actions from its
config:run against the hub and are saved as the snapshotpre-update, replaced each window. -
Update: the
--aftercommand runs withsh -cin the site's project folder (the one holding its.echo/), withRHYTHM_ECHO_SITE=<id>andRHYTHM_ECHO_URL=<the hub>set. Its output is printed as<id>: <line>. -
Compare: the actions run again and are compared with
pre-update, with the site config'schecks:levels and each action'signore:, asrhythm echo comparedoes.
The last line per site is Something broke: …, Something changed: … or Nothing broke: …, <id>: couldn't compare: <error> when the compare couldn't run, with (the update failed: <error>) after it when the command failed. Each window keeps run.json, comparison.json and schedule.json in <store>/sites/<id>/runs/ (104 windows per site), which is what the agency report reads.
rhythm echo schedule "Tue 02:00" --store /home/you/hub/store --after trueNext window: Tue 27 Oct 02:00 UTC (in 1d 11h30m)
Without --now or --once, schedule waits for each window, runs it and waits for the next, until you stop it (exit 0). It prints the next window on stderr each time. Times are local.
| Schedule | Runs |
|---|---|
"Tue 02:00" |
every Tuesday at 02:00 |
"Mon,Thu 03:30" |
Mondays and Thursdays |
"daily 02:00", "everyday 02:00"
|
every day |
"weekdays 22:00", "weekends 06:00"
|
Monday to Friday, or Saturday and Sunday |
"02:00" |
a bare time: every day |
Day names work in any case, short or long. A time a daylight-saving change skips moves to the next matching day. Anything else is refused (exit 2):
rhythm echo schedule: schedule "Tue 2am": want days and a time, like "Tue 02:00", "Mon,Thu 03:30", "daily 02:00" or "weekdays 22:00"
| Flag | Default | Does |
|---|---|---|
<when> |
The schedule, in quotes. Not needed with --now. |
|
--store <dir> |
(required) | The hub's store. |
--sites <file> |
sites.yaml |
The sites.yaml, as rhythm echo hub reads it. |
--only <ids> |
all | A comma list of site IDs to run. |
--after <command> |
(required) | The update. |
--after-timeout <d> |
30m |
Stop the command after this long. |
--snapshot <name> |
Compare with this snapshot instead of taking one first. | |
--url <url> |
http://127.0.0.1:8025 |
The hub's API. |
--ca <file> |
the hub's self-signed certificate in the store | The certificate to trust for an HTTPS hub. |
--now |
Run one window now and exit. | |
--once |
Wait for the next window, run it and exit. |
--sites names the file and --only picks the sites:
rhythm echo schedule: --sites client-a: no such file; --sites names the sites.yaml (as for rhythm echo hub) and --only picks the sites, like --only client-a
rhythm echo schedule: --only: no site "client-z"; the sites are: client-a
rhythm echo schedule: say when, like "Tue 02:00", or run one window now with --now
With --now and --once: 0 nothing broke, 1 a site broke or its update failed, 2 a usage error or a bad sites file, 3 couldn't run (no site could be compared at all, such as with the hub down). Ctrl+C during a window exits 130 with rhythm echo schedule: canceled; the window is partial.
The --after command runs as your user, with the hub's tokens removed from its environment: every variable sites.yaml names (the read token's and each site's) plus any other variable holding one of those values. So it can't ask the hub for other sites' mail. It can still read the store, which holds every site's mail, unless it runs as a user that can't:
rhythm echo schedule "Tue 02:00" --store /srv/echo --after "sudo -u www-data wp plugin update --all"Every request schedule makes for a site carries X-Echo-Site: <id>, so the hub ties untagged mail (a queued job, plain SMTP) during that site's actions to that site only.
← Agency hub and reports · Home · MCP server →
rhythm · Useful ideas. Working systems. · Check only sites you own or have permission to test. Keep staging sealed (responsible use) · This wiki is published from wiki/ in the rhythm repository; suggest changes there with a pull request.
Get started
rhythm in depth
Tuner
- Overview
- Your first scan
- Reading results
- Choosing checks
- Requests and politeness
- Output and reports
- Batch scans
- Local scans
- Integrity and malware
- Changes and notifications
Tuner in depth
- Known vulnerabilities
- PHP advisories
- CI and code scanning
- GitHub Action
- Config file
- Watch and serve
- Writing checks
- Check packs
- Finding reference
- CLI reference
- Coming from Wordfence CLI or WPScan
- FAQ and troubleshooting
Soundcheck
- Overview
- Your first check
- Reading results
- Review and accept
- Discovery
- Page health
- Visual changes
- Interactions
- Forms and flows
- Cache
- Speed
- Accessibility and SEO
Soundcheck in depth
- CI
- CI baselines and PR comments
- Configuration
- Error rules and exec
- WordPress updates
- Fleet and client reports
- History
- Import from BackstopJS and Lost Pixel
- Firefox and WebKit
- CLI reference
- FAQ and troubleshooting
- Benchmark
Echo
- Overview
- Your first run
- Connectors
- Sealing staging
- Echo Inbox
- Messages and checks
- Checks and rules
- Attachments
- Actions and compare
- With Soundcheck
- Replay
- Deliverability
Echo in depth
- Docker and DDEV
- Agency hub and reports
- Schedule
- MCP server
- Conformance kit
- CI
- Configuration
- API
- CLI reference
- FAQ and troubleshooting
- Benchmark
Project