Skip to content
Back to skills

Pb Connect Strava

ASecurity

Connect a Strava account and sync activities (one-time setup, then auto-refresh)

  • 3 stars
  • 0 votes
  • 0 copies
  • 4 views
  • Added May 27, 2026
data-aipythongogitapisecurity

Works with

  • cli
  • api

Security analysis

A100/100

Scanned May 27, 2026

npx -y skills add seungwee-choi/oh-my-personal-best --skill pb-connect-strava --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Pb Connect Strava?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Pb Connect Strava
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/seungwee-choi-pb-connect-strava/badge)](https://www.skillsdirectory.com/skills/seungwee-choi-pb-connect-strava)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: pb-connect-strava
description: Connect a Strava account and sync activities (one-time setup, then auto-refresh)
argument-hint: "[--client-id ID --client-secret SECRET] or just run it and follow the prompts"
level: 3
---

<Purpose>
Connects the runner's Strava account so activities sync into the training log and keep syncing
without re-auth. Strava has no "paste a token" path — every token is bound to a Strava API app
and access tokens expire every 6 hours — so the seamless flow is: the runner creates their OWN
personal Strava app once (no review needed for their own data), then this skill runs the OAuth
dance automatically via a localhost callback (the runner only clicks "Authorize" in the browser)
and stores a refresh-token credential that `import_strava.py` auto-refreshes from then on.
</Purpose>

<Use_When>
- The runner wants to import from Strava, or says "connect strava", "스트라바 연동", "sync strava"
- During `/pb-setup` when the runner picks Strava as their data source
- A **Garmin or COROS** user who wants auto-sync: those platforms have no individual API (business/partner-only), but both watches can auto-sync to Strava with one toggle in their app — so connecting Strava here pulls their Garmin/COROS activities too. (Prefer this over the gated/undocumented Garmin/COROS APIs.)
</Use_When>

<Do_Not_Use_When>
- The runner only has COROS/Garmin `.fit` files or a CSV → use `/pb-log` (no Strava app needed)
- They just want a one-time dump and don't want to make an app → suggest Strava's "Request your archive" (Settings → My Account) and import the resulting `.fit`/CSV via `/pb-log`
</Do_Not_Use_When>

<Steps>

## Step 1 — Create a personal Strava app (one-time, ~2 min, no review)
Tell the runner to open **https://www.strava.com/settings/api** and create an app with these exact values:
- **Application Name:** anything (e.g. `my-ompb`)
- **Category:** Data Importer
- **Club:** leave blank
- **Website:** anything (e.g. `http://localhost`)
- **Authorization Callback Domain:** `localhost`  ← MUST be exactly this, or the connect step fails
Then copy the **Client ID** and **Client Secret** from that page.

> This app is private to the runner and only ever touches their own data. App *review* is only
> required to let *other* athletes connect — not for personal single-user use.

## Step 2 — Run the OAuth connect (automated)
With the runner's Client ID and Client Secret:
```
python3 "$CLAUDE_PLUGIN_ROOT/scripts/strava_connect.py" --client-id <ID> --client-secret <SECRET>
```
This opens the browser to Strava's authorize page (scope `activity:read_all`), runs a one-shot
localhost callback server, captures the returned code, exchanges it, and writes
`$OMPB_HOME/strava.json` (chmod 600 — contains secrets, gitignored, never commit). The runner
only clicks **Authorize**. If no browser opens (headless), re-run with `--no-browser` and have
them open the printed URL manually. The command blocks until they authorize (≤5 min timeout).

## Step 3 — First sync
```
python3 "$CLAUDE_PLUGIN_ROOT/scripts/import_strava.py"
```
Refreshes the access token automatically, pages through all activities, normalizes them
(running → easy/long, other sports → cross), and appends new ones to
`$OMPB_HOME/training-log.jsonl` (deduped by `source_id`). Report the summary (new activities, by sport).

## Step 4 — Hand off
- If the runner is new, continue `/pb-setup` (profile bootstrap + first report).
- Ongoing: re-run `import_strava.py` (or `/pb-log strava`) anytime to pull new activities — no
  re-auth needed; the stored refresh token mints fresh access tokens.

</Steps>

<Security>
- `strava.json` holds `client_secret` + `refresh_token`. It lives under `$OMPB_HOME` (gitignored) and is written chmod 600. Never print the secret, never commit the file.
- Scope is `activity:read_all` (read-only, includes private activities). OMPB never writes to Strava.
</Security>

<Stop_Conditions>
- `$CLAUDE_PLUGIN_ROOT` unset (not an installed plugin) → run the scripts from the repo with `python3 scripts/...`.
- Token exchange/refresh fails → most often the Callback Domain wasn't `localhost`, or the client id/secret were mistyped; have the runner re-check the app settings and retry.
- Strava API returns 429 → rate limited; wait 15 minutes and re-run (sync resumes via dedup).
</Stop_Conditions>

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.