A CLI tool for syncing and analyzing rowing data from your Concept2 Logbook.
go install github.com/richhaase/c2/cmd/c2@latestOr pin a release:
go install github.com/richhaase/c2/cmd/c2@v0.5.0Binaries for macOS and Linux are also attached to each release.
To build from a checkout:
git clone https://github.com/richhaase/c2.git
cd c2
make install# Configure token and goals
c2 setup
# Sync workouts
c2 sync
# Check your progress
c2 statusConfigure your token and goal settings:
c2 setupGet your personal access token from log.concept2.com under Settings → Developer. The setup wizard will prompt for your token, goal target, and date range.
Pull new workouts from the Concept2 API:
c2 sync# Show last 10 workouts
c2 log
# Show last 25 workouts
c2 log -n 25Interval workouts are tagged with [IVL rest M:SS.S] so they're visually
distinct from continuous pieces. The rest duration is surfaced because, for
interval workouts, the displayed time (time_formatted) is elapsed time
including rest, while the displayed pace is correctly computed from work
time only. For example:
04/11 5,000m 28:35.4 2:51.5/500m 24spm 112bpm 107df
04/11 3,000m 20:22.6 2:23.8/500m 30spm 152bpm 108df [IVL rest 6:00.0]
The second row is 6x500m with ~1 min rest between reps: 20:22.6 elapsed =
14:22.6 work + 6:00 rest. The 2:23.8/500m pace is the work pace.
Track progress toward your distance goal:
c2 statusView weekly trends for pace, volume, stroke rate, and heart rate:
# Last 8 weeks (default)
c2 trend
# Last 12 weeks
c2 trend -w 12Generate a self-contained HTML progress report. Coaching content from the
store renders automatically when present: the latest narrative (as "Coach's
Report"), notes from the last 14 days, and the training-plan excerpt.
c2 report --data emits the entire report as structured JSON
(c2.report.v1) — the machine-readable twin of the HTML, for agents and
custom rendering surfaces:
# Write to a temp file and open it in your browser
c2 report
# Custom output path
c2 report -o ~/Desktop/rowing.html
# Write the file but don't open it
c2 report --no-open
# Show more weeks of history
c2 report -w 16Export workouts to CSV, JSON, or JSONL:
# CSV to stdout
c2 export
# JSON format
c2 export -f json
# Filter by date range
c2 export --from 2026-01-01 --to 2026-03-01
# Pipe to file
c2 export -f jsonl > workouts.jsonlThe CSV export includes workout_type, rest_time_tenths, and
rest_distance columns so interval workouts are fully distinguishable from
continuous pieces without having to consult the full JSON export.
# Full detail for one workout: splits, stroke summary, comments
c2 show last
c2 show 118212501
# Derived analytics (the arithmetic, so coaches only interpret)
c2 stats weekly -w 12 # volume/pace/SPM/HR per week
c2 stats goal # trajectory + projection
c2 stats splits last # per-split pace/HR + shape (even/negative/positive)
c2 stats hr-pace -w 8 # avg HR by steady pace band, with early→late driftAll of these accept --json.
The store holds coaching content alongside workout data, so any coach — human or AI, on any machine — reads and writes the same facts:
# Subjective report after a row (athlete voice, linked to the workout)
c2 note add --type subjective --workout last "felt slow early, opened up late"
# Coach observations and durable lessons
c2 note add --type lesson --author coach "HR cap is the rule, not pace"
# Review
c2 note list --since 2026-06-01
c2 note list --workout 118212501 --json
c2 show last # linked notes appear in workout detail
# Training plan and coaching playbook (whole-document set/show)
c2 plan set plan.md
c2 playbook show
# Dated coaching report narratives
c2 narrative add 2026-07-05 report.md
c2 narrative showNotes are stored one file each for the most recent 7 days (safe under iCloud/
Dropbox sync), then automatically compacted into one archive file per year
(c2 data compact runs after every sync). c2 data doctor validates the
whole store.
log, status, trend, show, stats, and data info accept --json and emit a stable
versioned envelope for scripts and AI agents:
{ "schema": "c2.status.v1", "generated_at": "2026-07-05T18:00:00.000Z", "data": { } }export -f json emits the same envelope (c2.export.v1) with the full
workout records under data.workouts. export -f jsonl stays one raw
workout per line for streaming.
Workout data and coaching data live in a single data directory,
chosen during c2 setup and stored as data_dir in config. Point it at a
synced folder (iCloud, Dropbox, a git repo) to share one store across
machines — the config file with your API token always stays machine-local
in ~/.config/c2/ (mode 600).
# Where is my data, and what's in it?
c2 data info
# Relocate the store (copies, verifies, updates config)
c2 data move ~/Documents/KnowledgeBase/c2-dataSetup validates the directory you pick: it creates it if missing (with confirmation), checks writability, adopts an existing c2 store it finds there, and refuses to save a path that fails validation.
Note: bare c2 prints help. Unknown commands error instead of falling
through to a default.
Config lives at ~/.config/c2/config.json. Created automatically on c2 setup.
{
"data_dir": "~/.config/c2/data",
"api": {
"base_url": "https://log.concept2.com",
"token": "YOUR_TOKEN"
},
"goal": {
"target_meters": 1000000,
"start_date": "2026-01-01",
"end_date": "2026-12-31"
},
"display": {
"date_format": "%m/%d"
}
}make check # fmt-check + vet + lint + race tests
make test # tests only
make build # build ./bin/c2
make run ARGS="log -n 5"MIT — see LICENSE