Watch every official Google site for Android and Android developers, and get a ranked, AI-triaged digest when something actually changes.
Self-hosted CLI. No cloud subscription. MIT.
Google ships Android news across dozens of properties: platform and AOSP release
notes, Android Studio and Gradle Plugin changelogs, the AndroidX feeds, the
Developers Blog, Material Design, YouTube, and many sections of
developer.android.com. Keeping up means babysitting a pile of RSS readers and
bookmarks, and most of what changes is a typo fix or a template reflow.
android-watcher checks a curated catalog of official sources on a schedule,
detects real changes (not cosmetic churn), uses Claude to decide what is worth
your attention and write a short description, ranks the result, and delivers a
digest to Slack or a desktop notification. When nothing substantive changed, it
says so instead of padding a digest with noise.
Install it once, run the interactive setup wizard, and receive a daily (or hourly, or weekly) digest.
Homebrew (recommended):
brew tap krayong/android-watcher https://github.com/krayong/android-watcher
brew trust krayong/android-watcher
brew install android-watcherThe tap points straight at this repo's Formula/, so brew upgrade tracks new
releases. (A bare brew install android-watcher without the tap only works once a
formula is accepted into homebrew-core.)
Homebrew 6.0+ refuses to load a formula from an untrusted third-party tap, so the
brew trust step is required; without it brew install fails with "Refusing to
load formula ... from untrusted tap." Older Homebrew versions don't need it.
PyPI (via uv or pipx):
uv tool install android-watcher # via uv
pipx install android-watcher # via pipxFrom source:
git clone https://github.com/krayong/android-watcher
cd android-watcher
uv tool install .Requires Python 3.11+.
AI prerequisite: The triage backend calls claude -p (the Claude CLI). No
API key is required; the CLI handles authentication. Install and authenticate
claude separately if you want AI triage. To skip it, set
[ai] mode = "off" and android-watcher still delivers a digest (every detected
change is marked substantive, with no description).
android-watcher # open the Textual setup wizard
android-watcher test # dry run: render the digest to stdout, send nothing
android-watcher run # one detection-triage-notify pass
android-watcher schedule install # install the native launchd / systemd / cron entry
android-watcher schedule status # confirm the entry is loaded and active
android-watcher schedule remove # uninstall the scheduled job
android-watcher doctor # health checks: prefixes, AI reachable, schedule active
android-watcher catalog # list and inspect the shipped source catalog
android-watcher --help # full flag referenceBare android-watcher opens the Textual setup wizard. It walks you through config
and writes a native scheduled job. The first pipeline run baselines each source
silently. It does not send a digest claiming every page is new.
Config lives at ~/.config/android-watcher/config.toml (honoring
$XDG_CONFIG_HOME) and is written with 0600 permissions. State (snapshots,
change history, delivery ledger) lives in a SQLite database under
~/.local/share/android-watcher/. Override the config path with --config PATH.
The setup wizard writes the file for you. To edit manually:
[schedule]
interval = "daily" # hourly | daily | weekly | cron
at = "09:00" # local time; ignored when interval = "cron"
cron = "" # raw cron expression; only used when interval = "cron"
[ai]
mode = "claude_cli" # claude_cli | off
model = "claude-sonnet-4-6"
[digest]
max_items = 10 # cap on change-groups shown in the message; the rest collapse into the full digest page
empty = "send" # send | skip (what to do when nothing substantive changed)
[sort]
# Optional per-source or per-category priority overrides (higher = ranked first).
# "android-developers-blog" = 90
[channels.slack]
enabled = true
bot_token = "${ANDROID_WATCH_SLACK_TOKEN}" # env-var ref recommended (bot token is a secret)
channel = "C0123456789" # channel ID (or #channel-name)
[channels.desktop]
enabled = false
sound = "Glass" # macOS notification sound; click opens the full digest
# Add your own URLs (same shape as catalog entries):
# [[custom_source]]
# id = "my-blog"
# name = "My Blog"
# category = "dev-blog"
# detector = "feed"
# url = "https://example.com"
# feed_url = "https://example.com/feed.xml"
# enabled = trueThe secret android-watcher uses is the Slack bot token. Use an environment-variable reference so the value is never written into the config file:
export ANDROID_WATCH_SLACK_TOKEN="xoxb-..."The config stores ${ANDROID_WATCH_SLACK_TOKEN} literally; the value is resolved
at runtime. Inline plaintext works but is discouraged.
A curated catalog of 41 official Android and Android-developer sources ships
inside the package. android-watcher catalog lists it. The setup wizard lets you
enable or disable catalog entries and add custom sources.
To propose a new official source, edit src/android_watcher/catalog/catalog.toml
and open a pull request (see CONTRIBUTING.md).
After the wizard completes, install the native scheduled job:
android-watcher schedule installOn macOS this writes a launchd plist to ~/Library/LaunchAgents/ and loads it
via launchctl. On Linux with systemd it writes a user timer and enables it;
run loginctl enable-linger $USER once so the timer fires after logout. On
Linux without systemd it writes a marked crontab block.
Confirm the job is active:
android-watcher schedule statusIf the machine was asleep during a scheduled cycle, android-watcher detects the missed run on the next wake and catches up automatically.
Secrets. The secret is the Slack bot token. The config file is written
0600. Prefer an environment-variable reference
(bot_token = "${ANDROID_WATCH_SLACK_TOKEN}") so plaintext values are never
written to disk.
Keep config out of git. If you keep your config under version control, never
commit a file with inline secrets. Add to .gitignore:
# android-watcher
config.toml
*.android-watcher.tomlThe TUI and --config warn when the config path is inside a git work tree,
because an accidental commit would expose your Slack bot token.
AI data egress. When [ai] mode = "claude_cli", the content of changed
pages is sent to the claude CLI for triage and description. For the shipped
catalog this is public Google documentation. If you add custom sources (such
as an internal wiki), that page content is also sent to claude. Set
[ai] mode = "off" for the no-egress path: no triage, no descriptions, no
page content leaves your machine.
Slack. The Slack bot token is treated as a bearer secret and is never logged.
| Command | What it does |
|---|---|
android-watcher |
Open the Textual setup wizard |
android-watcher run [--force] |
One detection-triage-notify pass |
android-watcher test |
Dry run: render digest to stdout, send nothing |
android-watcher doctor |
Health checks: prefixes, AI reachable, schedule active |
android-watcher catalog |
List and inspect the shipped source catalog |
android-watcher schedule install |
Install the native scheduled job |
android-watcher schedule status |
Show whether the job is loaded and active |
android-watcher schedule remove |
Uninstall the scheduled job |
android-watcher --config PATH |
Use a specific config file |
android-watcher --version |
Print version |
See CONTRIBUTING.md. Short version: add a source by editing
catalog.toml; add a detector, triager, or channel by implementing the
protocol, registering the name, and adding a fixture-backed test. TDD, ruff,
and pytest must pass.
For questions or support, open an issue on GitHub or email androidwatcher@krayong.com. Security reports: see SECURITY.md.
MIT.