Skip to content

feat: add whoop-setup CLI onboarding wizard#48

Open
ald0405 wants to merge 7 commits into
mainfrom
claude/cli-onboarding-setup-9PJE8
Open

feat: add whoop-setup CLI onboarding wizard#48
ald0405 wants to merge 7 commits into
mainfrom
claude/cli-onboarding-setup-9PJE8

Conversation

@ald0405

@ald0405 ald0405 commented Apr 10, 2026

Copy link
Copy Markdown
Owner

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

claude added 4 commits April 10, 2026 16:29
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
@github-actions

github-actions Bot commented Apr 10, 2026

Copy link
Copy Markdown

📝 Changes in this PR

✨ Features

  • 8c8f584 feat: add WHOOP developer app walkthrough to setup wizard
  • 145f35f feat: improve setup wizard flow, Withings gate, LangSmith, and Telegram hardening
  • 386e721 feat: complete onboarding wizard with preflight, architecture overview, Postgres, launchd, and OAuth notice
  • 8d4ca21 feat: TfL numbered line picker + live station search in setup wizard
  • 2f6487f feat: dynamic Thames tidal station discovery from EA API
  • 3bae19d feat: location config + TFL/Thames feature flags for non-London users
  • a5e5b75 feat: add whoop-setup CLI onboarding wizard

🐛 Bug Fixes

📚 Documentation

🧹 Refactoring

🧪 Testing

🔧 Maintenance

📦 All Commits

  • 8c8f584 feat: add WHOOP developer app walkthrough to setup wizard
  • 145f35f feat: improve setup wizard flow, Withings gate, LangSmith, and Telegram hardening
  • 386e721 feat: complete onboarding wizard with preflight, architecture overview, Postgres, launchd, and OAuth notice
  • 8d4ca21 feat: TfL numbered line picker + live station search in setup wizard
  • 2f6487f feat: dynamic Thames tidal station discovery from EA API
  • 3bae19d feat: location config + TFL/Thames feature flags for non-London users
  • a5e5b75 feat: add whoop-setup CLI onboarding wizard

This changelog is automatically generated from commit messages

claude added 3 commits April 10, 2026 21:24
…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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants