feat: add whoop-setup CLI onboarding wizard#48
Open
ald0405 wants to merge 7 commits into
Open
Conversation
Introduces a guided first-time setup wizard (whoop-setup / make setup) that walks new users through entering API credentials, writing .env, and initialising the local database — replacing the manual copy-and-edit workflow described in the README. - whoopdata/setup.py: interactive wizard using rich Prompt/Confirm; handles required (WHOOP, Withings, OpenAI) and optional (weather, Telegram) credentials; skips re-run if .env already exists unless the user explicitly confirms; shows a next-steps table on completion - pyproject.toml: registers whoop-setup entry point - Makefile: adds setup target and documents it in the help output - README.md: replaces manual .env instructions with make setup as the recommended onboarding step; retains the manual copy path as a fallback https://claude.ai/code/session_01GN4GkteiKYa5RdEa4qyQ7c
Adds proper location and country configuration so weather is geocoded correctly for any city, and gates TfL/Thames tidal features behind explicit opt-in flags so non-London users are not broken by London- specific integrations. agent/settings.py - DEFAULT_LOCATION now reads from env var (falls back to "Canary Wharf") - DEFAULT_COUNTRY reads DEFAULT_COUNTRY env var (falls back to "GB") - TFL_ENABLED flag (ENABLE_TFL env var, default false) - THAMES_TIDES_ENABLED flag (ENABLE_THAMES_TIDES env var, default false) - TFL_KEY_LINES reads TFL_KEY_LINES env var so monitored lines are configurable without touching source code services/transport_service.py - TravelAPI.__init__ reads key_lines from settings.TFL_KEY_LINES instead of hardcoding "South Quay / Canary Wharf" lines services/insight_context_service.py - DEFAULT_LOCATION sourced from settings (env-driven) - TravelAPI and TideService are only instantiated when the respective feature flags are true; methods return empty dict/list otherwise so dashboard and daily-plan flows degrade gracefully for non-London users agent/tools.py - get_transport_status_tool: returns a clear "not enabled" message when TFL_ENABLED=false instead of making a doomed API call - get_tide_times_tool / get_perfect_walk_times_tool: same guard for THAMES_TIDES_ENABLED=false setup.py (whoop-setup wizard) - New "Location & regional features" section asks for city and country - Detects UK entries (GB/UK/United Kingdom/England) and conditionally offers the London-specific feature questions - Non-UK users: ENABLE_TFL=false and ENABLE_THAMES_TIDES=false set silently with a one-line note — no London questions shown - UK + London: prompts for TfL lines to monitor and preferred tide station (0001/0003/0007) with reference lists shown inline - _write_env updated to include Location and London Regional Features sections with inline comments - _show_next_steps includes TfL/tide status notes when enabled .env.example - Documents DEFAULT_LOCATION, DEFAULT_COUNTRY, ENABLE_TFL, ENABLE_THAMES_TIDES, TFL_KEY_LINES, DEFAULT_TIDE_STATION_ID/NAME https://claude.ai/code/session_01GN4GkteiKYa5RdEa4qyQ7c
Previously the codebase had only 3 hardcoded stations (Silvertown,
Charlton, Tower Pier). This replaces the static list with a live
lookup against the Environment Agency Flood Monitoring API so users
can see and pick from the full set of Thames tidal gauges.
tide_service.py
- Expanded STATIONS dict comments to be clearer about coverage
- New async list_thames_tidal_stations() method: queries
/id/stations?type=TideGauge&riverName=River+Thames, returns
[{id, name, lat, lon}] sorted west→east (upstream→downstream)
- Gracefully falls back to the 3 well-known hardcoded stations on
any network or API error
tide_routes.py
- GET /api/v1/data/tides/stations now calls list_thames_tidal_stations()
to return the live EA station list instead of a static JSON blob
- Response shape preserved: {stations: [...], default: "0001"}
setup.py
- Adds _TIDE_STATIONS_FALLBACK (replaces old _TIDE_STATIONS dict)
- New _fetch_tide_stations() helper: calls list_thames_tidal_stations()
via asyncio.run(), falls back to _TIDE_STATIONS_FALLBACK if offline
- Thames tides section of the wizard now fetches and displays all
available stations in a table before prompting for selection
- Station ID validation is lenient: warns but keeps the user's entry
if the ID is not in the fetched list (EA has many stations not in
the fallback set)
https://claude.ai/code/session_01GN4GkteiKYa5RdEa4qyQ7c
Replaces the free-text line input and hardcoded Canary Wharf stations
with a proper interactive selection flow backed by the TfL API.
transport_service.py
- TFL_LINE_CATALOGUE: complete static list of all TfL lines with their
API IDs and modes (tube/dlr/elizabeth-line/overground/tram/cable-car)
used as a fallback when the API is unreachable
- list_available_lines(): fetches the live line list from the TfL API,
falls back to TFL_LINE_CATALOGUE; returns [{id, name, mode}] sorted
alphabetically
- search_stations(query, modes, limit): queries the TfL StopPoint Search
API by name fragment (handles ~500 stations), returns [{id, name,
lines}] — used by the wizard to let users find any station by typing
part of its name
- TravelAPI.__init__ now reads key_stations from settings.TFL_KEY_STATIONS
so arrival boards are configurable without touching source code; falls
back to the original Canary Wharf defaults when not set
settings.py
- TFL_KEY_STATIONS: parses TFL_KEY_STATIONS env var from pipe-separated
"Label:NaptanID" pairs into a dict; None when unset (triggers fallback)
- _parse_tfl_stations() helper handles the parsing cleanly
setup.py
- _fetch_tfl_lines(): fetches live from TfL API via TravelAPI, falls back
to TFL_LINE_CATALOGUE; called once at setup time
- _prompt_tfl_lines(): displays all lines in a numbered table; user picks
by entering comma-separated numbers (e.g. "3,8,12") rather than typing
names; pre-selects numbers matching any previously configured lines
- _prompt_tfl_stations(): interactive station search loop — user types a
name fragment, sees up to 10 results in a numbered table, picks one,
gives it a label, then chooses whether to add another; handles all ~500
TfL stations without listing them all; gracefully skips if TfL API is
unreachable during offline setup
- _prompt_location() wires both helpers into the London feature block
- _write_env() now includes TFL_KEY_STATIONS in the London section
.env.example
- Documents TFL_KEY_LINES, TFL_KEY_STATIONS (with format example and API
URL for manual lookup), and tide station fields with full context
https://claude.ai/code/session_01GN4GkteiKYa5RdEa4qyQ7c
📝 Changes in this PR✨ Features
🐛 Bug Fixes📚 Documentation🧹 Refactoring🧪 Testing🔧 Maintenance📦 All Commits
This changelog is automatically generated from commit messages |
…w, Postgres, launchd, and OAuth notice - _preflight_check(): verifies uv, runs uv sync if .venv missing, checks Python 3.10+ - _show_architecture(): Rich table explaining all platform components and where they run - _setup_postgres(): explains in-memory vs Postgres, Docker path (make postgres-up), Homebrew alternative, and manual URL entry; writes AGENT_POSTGRES_URL to .env - _setup_launchd_services(): macOS-only section listing all 6 launchd daemons, checks already-loaded services, offers make services-up - _setup_database(): now shows the SQLite file path and explains it is separate from Postgres before creating tables - _show_next_steps(): prominent WHOOP OAuth 2.0 panel explaining the browser redirect that happens on the very first make etl run - main(): wired all five new phases into the correct sequence https://claude.ai/code/session_01GN4GkteiKYa5RdEa4qyQ7c
…am hardening Flow reorder: - Location/country is now asked FIRST so the wizard knows the region before collecting credentials; non-London users skip TfL/tides sections immediately Withings: - Moved out of REQUIRED_CREDENTIALS — gated behind "do you have a Withings scale?" Users without the device skip those two credentials entirely LangSmith: - New _setup_langsmith() section explains tracing and observability - Panel explains what LangSmith does, links to smith.langchain.com, free tier note - Prompts for LANGCHAIN_API_KEY, sets LANGCHAIN_TRACING_V2, LANGCHAIN_PROJECT - Disabled (LANGCHAIN_TRACING_V2=false) if user skips Telegram: - Replaced the single-line token prompt with a full _setup_telegram() function - Step-by-step BotFather walkthrough panel (@Botfather → /newbot → copy token) - Security panel explaining why TELEGRAM_ALLOWED_USER_IDS matters - Instructions to get user ID via getUpdates API or @userinfobot - Prompts for TELEGRAM_ALLOWED_USER_IDS and TELEGRAM_ALLOWED_CHAT_IDS - Warning printed if no user ID is set (bot will accept anyone) .env writer: - Added TELEGRAM_ALLOWED_USER_IDS, TELEGRAM_ALLOWED_CHAT_IDS, LANGCHAIN_* keys to the structured section list https://claude.ai/code/session_01GN4GkteiKYa5RdEa4qyQ7c
New _explain_whoop_app() panel shown before WHOOP credential prompts: - Explains that your WHOOP membership account is the developer account - Step-by-step: developer.whoop.com → My Apps → Create App - Shows the exact redirect URI to set: http://localhost:8765/callback - Lists all required scopes (read:recovery, read:sleep, read:workout, read:profile, read:body_measurement, offline) - Calls out that the 'offline' scope is critical for the refresh token - Explains headless operation: first run opens browser once, then the ETL job (which runs every 45 minutes) silently refreshes the token - Notes token storage in .whoop_tokens.json and that it is gitignored - "Press Enter when ready" gate so users don't race past it https://claude.ai/code/session_01GN4GkteiKYa5RdEa4qyQ7c
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Introduces a guided first-time setup wizard (whoop-setup / make setup)
that walks new users through entering API credentials, writing .env, and
initialising the local database — replacing the manual copy-and-edit
workflow described in the README.
handles required (WHOOP, Withings, OpenAI) and optional (weather,
Telegram) credentials; skips re-run if .env already exists unless
the user explicitly confirms; shows a next-steps table on completion
recommended onboarding step; retains the manual copy path as a fallback
https://claude.ai/code/session_01GN4GkteiKYa5RdEa4qyQ7c