Skip to main content

Self-hosted CLI that watches Google's official Android sites and delivers AI-triaged change digests.

Project description

Android Watcher

Android Watcher

Watch every official Google site for Android and Android developers, and get a ranked, AI-triaged digest when something actually changes.

CI PyPI Python 3.11+ License: MIT Ruff pre-commit

Self-hosted CLI. No cloud subscription. MIT.


What it does

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 email, Slack, or Telegram. 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.


Install

Homebrew (recommended):

brew tap krayong/android-watcher https://github.com/krayong/android-watcher
brew install android-watcher

The 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.)

PyPI (via uv or pipx):

uv tool install android-watcher     # via uv
pipx install android-watcher        # via pipx

From 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).


Quickstart

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 reference

Bare 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.


Configuration

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.email]
enabled = true
smtp_host = "smtp.example.com"
smtp_port = 465                                    # TLS required: implicit (465) or STARTTLS
username = "you@example.com"
password = "${ANDROID_WATCH_SMTP_PASSWORD}"        # env-var ref recommended; see Security
from = "you@example.com"
to = "you@example.com"

[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.telegram]
enabled = false
bot_token = "${ANDROID_WATCH_TELEGRAM_TOKEN}"     # env-var ref recommended (bot token is a secret)
chat_id = "123456789"

# 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 = true

Secrets

The secrets android-watcher uses are the SMTP password, the Slack bot token, and the Telegram bot token. Use environment-variable references so those values are never written into the config file:

export ANDROID_WATCH_SMTP_PASSWORD="hunter2"
export ANDROID_WATCH_SLACK_TOKEN="xoxb-..."
export ANDROID_WATCH_TELEGRAM_TOKEN="1234567890:AAF..."

The config stores ${ANDROID_WATCH_SMTP_PASSWORD} literally; the value is resolved at runtime. Inline plaintext works but is discouraged.


The catalog

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).


Scheduling

After the wizard completes, install the native scheduled job:

android-watcher schedule install

On 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 status

If the machine was asleep during a scheduled cycle, android-watcher detects the missed run on the next wake and catches up automatically.


Security and privacy

Secrets. The secrets are the SMTP password, the Slack bot token, and the Telegram bot token. The config file is written 0600. Prefer environment-variable references (password = "${ANDROID_WATCH_SMTP_PASSWORD}") 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.toml

The TUI and --config warn when the config path is inside a git work tree, because an accidental commit would expose your SMTP password, Slack bot token, or Telegram 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.

SMTP transport. SMTP enforces TLS (implicit on port 465 or mandatory STARTTLS) with certificate verification. It fails closed rather than downgrading to plaintext.

Slack and Telegram. The Slack bot token and Telegram bot token are treated as bearer secrets and are never logged.


Commands

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

Contributing

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.


Contact

For questions or support, open an issue on GitHub or email androidwatcher@krayong.com. Security reports: see SECURITY.md.


License

MIT.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

android_watcher-1.0.0.tar.gz (1.5 MB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

android_watcher-1.0.0-py3-none-any.whl (1.4 MB view details)

Uploaded Python 3

File details

Details for the file android_watcher-1.0.0.tar.gz.

File metadata

  • Download URL: android_watcher-1.0.0.tar.gz
  • Upload date:
  • Size: 1.5 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for android_watcher-1.0.0.tar.gz
Algorithm Hash digest
SHA256 0844583243b9d94ef4211c80a8be6e5b0efac44d21bdb224aa6b02a5670cc7c3
MD5 fd8593a826a4b121a1c89d8e44bee36d
BLAKE2b-256 315c0ac31004a57aaa32b117c1d318cb5c8256adae9f95b7c874187335f47b3b

See more details on using hashes here.

File details

Details for the file android_watcher-1.0.0-py3-none-any.whl.

File metadata

File hashes

Hashes for android_watcher-1.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 f30a68299b679081fa6914d5979319ef2bdce6fbe5b2509e6c0bf99f15727e73
MD5 884815a36643cb2456713b2040f239d3
BLAKE2b-256 2a60200efb52d9a2c1db3c090884b158d051f4ad138956cd4be0f21a5ddca7df

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page