Beyond Cortex

VOLTRA Workout Data

Use when the user asks about VOLTRA or Concept2 Rowing/Ski workout history, recent workouts, sets, reps, training volume, force, velocity, power, fatigue, progress trends, movement performance, or data completeness. Fetch and analyze training data through Cortex. When "rowing" or "skiing" is ambiguous, distinguish VOLTRA cardio records from the matching Concept2 records and combine clearly labeled results when the user wants an overall summary.

Use the local voltra command as the single data entry point. Do not bypass Cortex to call the Beyond backend API directly. Do not expose the full VOLTRA API Key in commands, logs, or responses. Concept2 Rowing and Ski queries are read-only; C2 record deletion is temporarily unsupported.

Prerequisites

Unless already confirmed in the current session, run:

where.exe voltra
voltra --version
voltra -v
voltra workout auth-check --json

If authentication fails, tell the user to set VOLTRA_API_KEY or run:

voltra config set-api-key "<VOLTRA API Key>"

Do not ask for the web URL to generate keys. The VOLTRA API key is obtained from the Beyond+ mobile app (Cortex beta section), not a web dashboard.

After auth, detect the user's unit preference: read the unit field from voltra workout list --page-size 1 --json. If no workout data exists, ask "lbs or kg?". Standard workout weight/force/volume fields are already unified to LBS regardless of unit — unit only signals the user's display preference. Isometric isometricResult force fields are an explicit exception and use N/N·s. If unit is "KG", convert standard *Lbs fields ÷ 2.205 → kg for user-facing display, but do not convert the N-based Isometric fields. If unit is "LBS", report values as-is. Always allow the user to override. For details, see references/field-units.md.

After auth, use local-time output for user-facing timestamps. Cortex timestamps are UTC by default. Add --local-time to display timestamps in local timezone with ISO 8601 offset (for example, 2026-06-10T20:45:32+08:00). --start / --end parameters always use UTC regardless of --local-time.

For Concept2 Rowing and Ski, workoutDate is already the record's local time and timezone contains its IANA timezone. Do not reinterpret C2 workoutDate with --local-time.

Source and Sport Resolution

The source and sport are independent dimensions. Do not use a Concept2 command just because the sport is rowing or skiing.

  • VOLTRA Cardio Rowing — a workout performed on VOLTRA. It appears in standard VOLTRA workout history as workout type 8; use workout list, sets, aggregate-sets, or aggregate-reps with --workout-type 8 where supported.
  • Concept2 Rowing — a Concept2 Logbook rowing record. Use the read-only workout c2-rowing ... commands.
  • VOLTRA Cardio Skiing — a workout performed on VOLTRA. It appears in standard VOLTRA workout history as workout type 9; use the same standard commands with --workout-type 9 where supported.
  • Concept2 Ski — a Concept2 Logbook skiing record. Use the read-only workout c2-ski ... commands.

When the user names only "rowing" or only "skiing" and asks for historical data or analysis, do not silently choose one source. For rowing, query VOLTRA workout type 8 and Concept2 Rowing when both are requested; for skiing, query VOLTRA workout type 9 and Concept2 Ski when both are requested. Label every result with both its source and sport. If the user names only Concept2 or C2, ask whether they mean Rowing or Ski. If the user names a source and sport explicitly, use only the matching source and sport. If the request would control a device, clarify the source first; this skill cannot control Concept2, and both C2 record types are read-only with deletion temporarily unsupported.

For an integrated rowing or skiing summary:

  1. Use the standard VOLTRA commands for workout type 8 or 9, and use the matching C2 command (c2-rowing or c2-ski) for Concept2.
  2. Align the time zone and date range before comparing results.
  3. Keep source-specific units and metrics explicit: VOLTRA cardio uses the standard workout contract; C2 distanceM is already meters, C2 pace fields require their own conversion, and C2 workoutDate is already local.
  4. Never merge or reuse IDs across sources or sports.

Quick Decision Guide

  • Recent training / training history: voltra workout list --page-size 10 --json
  • Single workout details: voltra workout sets <workout-id> --json
  • Per-rep breakdown of a set: voltra workout reps <workout-id> <set-id> --json
  • Isometric test results: voltra workout list --workout-type 5 --json, then voltra workout sets <workout-id> --json
  • Unqualified rowing history or comparison: resolve VOLTRA workout type 8 versus Concept2 Rowing; see Source and Sport Resolution
  • VOLTRA Cardio Rowing records: voltra workout list --workout-type 8 --page-size 10 --json
  • Concept2 Rowing records: voltra workout c2-rowing list --page-size 10 --json
  • One Concept2 Rowing workout with stroke data: voltra workout c2-rowing detail <workout-id> --json
  • Concept2 Rowing monthly totals: voltra workout c2-rowing monthly --timezone <IANA> --json
  • Unqualified skiing history or comparison: resolve VOLTRA workout type 9 versus Concept2 Ski; see Source and Sport Resolution
  • VOLTRA Cardio Skiing records: voltra workout list --workout-type 9 --page-size 10 --json
  • Concept2 Ski records: voltra workout c2-ski list --page-size 10 --json
  • One Concept2 Ski workout with stroke data: voltra workout c2-ski detail <workout-id> --json
  • Concept2 Ski monthly totals: voltra workout c2-ski monthly --timezone <IANA> --json
  • Set/rep counts, volume, duration, movement distribution, weekly trends: voltra workout aggregate-sets --json
  • Force, velocity, power, work, rep quality, fatigue: voltra workout aggregate-reps --json
  • Delete confirmed Beyond app records: voltra workout records delete <workout-id>... --yes --json
  • Key or config issues: voltra workout auth-check --json, then voltra config show --json if needed
  • Clear local key: voltra config clear-api-key --json

Command Index

These are the stable commands available to this skill:

CommandPurpose
voltra workout auth-check --jsonVerify the current VOLTRA API Key
voltra workout list ... --jsonList workouts, locate training records
voltra workout sets <workout-id> --jsonView sets for a single workout
voltra workout reps <workout-id> <set-id> --jsonView per-rep data for a set
voltra workout c2-rowing list ... --jsonList the current user's Concept2 Rowing records (read-only)
voltra workout c2-rowing detail <workout-id> --jsonView one Concept2 Rowing record and cumulative stroke data (read-only)
voltra workout c2-rowing monthly --timezone <IANA> ... --jsonSummarize Concept2 Rowing records by month (read-only)
voltra workout c2-ski list ... --jsonList the current user's Concept2 Ski records (read-only)
voltra workout c2-ski detail <workout-id> --jsonView one Concept2 Ski record and cumulative stroke data (read-only)
voltra workout c2-ski monthly --timezone <IANA> ... --jsonSummarize Concept2 Ski records by month (read-only)
voltra workout aggregate-sets ... --jsonCross-workout set-level aggregates
voltra workout aggregate-reps ... --jsonCross-workout rep-level aggregates
voltra workout records delete <workout-id>... --yes --jsonPermanently delete confirmed current-user Beyond app workout records and sets after confirmation
voltra config show --jsonCheck if a local key is configured (returns masked key only)
voltra config clear-api-key --jsonDelete the local stored key (does not revoke the remote token)

The public C2 commands are sport-specific: use c2-rowing for Concept2 Rowing and c2-ski for Concept2 Ski. Both commands are read-only; there is no unfiltered public C2 command that mixes the two sports.

Command References

For non-trivial analysis tasks, read the matching reference first:

NeedReference
Key setup, auth failures, config boundariesreferences/auth-and-config.md
Workout lists, single workouts, set/rep drill-downreferences/drill-down.md
Aggregate commands, time ranges, filtersreferences/aggregates.md
Analysis workflows, output structure, common pitfallsreferences/analysis-recipes.md
Field naming, unit suffixes, conversion rulesreferences/field-units.md

Isometric Test Results (workoutType 5)

Historical Isometric results are available through the standard workout APIs. Use workout list --workout-type 5 to locate a test, then workout sets <workout-id> to read its set-level isometricResult. The workout list contract is unchanged and its maxPullForceLbs is the test's peak force summary in pounds.

When present, isometricResult contains:

  • peakForceN: peak force in N.
  • rfdNPerSec: rate of force development in N/s.
  • timeToPeakForceMs: time to peak from the run-segment start, in ms.
  • impulseNSec: impulse in N·s.
  • testTimeMs: run-segment duration in ms; it excludes pre and post segments.
  • forceDataRateHz: force-curve sample rate, normally 100 or 500 Hz.

The nested Isometric force fields use N/N·s even though standard *Lbs fields use pounds. Convert explicitly when comparing them: 1 lbf = 4.4482216152605 N. timeToPeakForceMs and testTimeMs are elapsed durations, not timestamps, so --local-time must not change them. Missing isometricResult or subfields are omitted; do not replace them with zero. The reps endpoint does not return the raw force curve, and realtime Isometric result streaming is outside this history API. The force trace has pre/run/post segments: testTimeMs is the run segment, timeToPeakForceMs starts at the run segment, and RFD uses the first 10 run samples. Treat impulseNSec as the returned device/service metric; its exact integration window cannot be independently reproduced from the Agent response.

Rules

  • Default to --json and parse structured output. Do not scrape plain text.
  • If the user says only "rowing" or "skiing", follow Source and Sport Resolution; never assume that it means Concept2 or VOLTRA without checking the request type.
  • Before running commands, convert relative times ("today", "last week", "last 30 days") to explicit yyyy-MM-ddTHH:mm:ss in UTC.
  • In responses, state the exact time range used in the user's local timezone.
  • For user-facing timestamp display, add --local-time to standard workout commands so JSON timestamps include local timezone offsets. C2 Rowing and Ski workoutDate values are already local and must be left as returned.
  • Isometric isometricResult.* values are already normalized by the backend. Do not apply the user's lbs/kg preference conversion to peakForceN, rfdNPerSec, or impulseNSec; only convert them to another unit when explicitly requested.
  • Always convert distance fields (*Mm) from millimeters to meters (÷1000) before display. Never show raw mm values to the user. C2 fields ending in M (for example, distanceM) are already meters and must not be divided again. See references/field-units.md.
  • Always convert duration fields (*Sec) to human-readable format (Xm Xs) for user-facing summaries. Preserve the raw decimal seconds when exact C2 data is requested.
  • Follow all unit conversion rules in references/field-units.md — weight (lbs/kg per user preference), distance (mm→m), duration (sec→human).
  • Do not expose internal IDs by default. This includes workout id, set id, actionIds, and deviceIdentity. Use descriptive labels instead (type name, time, position, movement name). If the user explicitly asks to delete records, IDs may be used internally to build the deletion command; first identify the target records from query results and obtain a second confirmation before executing it.
  • To resolve actionId → exercise name, use voltra actions get <id> or voltra actions list --json. The action catalog is cached locally. Common defaults: actionId=33 → "Free Exercises".
  • To capture account preferences, run voltra whoami --json; this refreshes ~/.voltra/user-preferences.json with preferred units and body measurements.
  • Do not infer long-term trends from a single page of workout list. Use aggregate commands for trends and totals.
  • Do not paginate indefinitely by default. Only fetch additional pages when the user asks for full history or the question genuinely requires more data.
  • workout list --page-size is capped at 50 by the backend, not Cortex. Do not request larger pages. For broader history, paginate manually or use aggregate-sets/aggregate-reps.
  • workout list / aggregate-* --start / --end span is capped at 365 days by the backend, not Cortex. Split longer queries into chunks. --start and --end are always UTC.
  • Cortex fetches data; interpretation, comparison, conclusions, and caveats are the AI layer's responsibility.

Out of Scope

  • Creating, listing, or revoking remote VOLTRA API Keys. Cortex can only store, view masked status, and clear local keys.
  • Modifying Concept2 Rowing or Ski records. The C2 command is read-only; deletion is temporarily unsupported.
  • Any training-history mutation other than the explicit, confirmed voltra workout records delete ... --yes command for the current user's Beyond app records. This deletion is physical and also removes set data. The backend returns data: null without per-ID results; missing, already-deleted, re-submitted, or foreign IDs may be silently ignored.
  • BLE device control.
  • Prescribing deterministic training plans based on insufficient data.
  • Managing custom curves. Custom Curve (workout type 6) records are queryable via workout list/sets/reps/aggregate-*, but curve CRUD lives in voltra custom-curve * — see voltra-device-training for those commands.
  • Session template CRUD. Workout history may reference actionId/workoutMode values that also appear in session templates, but creating/updating/deleting session templates is owned by voltra-device-training (the voltra session * commands). Use that skill for template authoring.

Guardrails

  • If authentication or config issues persist and the cause is unclear, suggest loading voltra-getting-started for first-time setup or voltra-cli-troubleshooting for diagnostics.
  • Before deleting Beyond app records, show the user which workouts will be targeted and ask for explicit confirmation. Never add --yes without that confirmation. The delete API returns null without confirming each ID, so do not claim that every requested ID was deleted.
  • If the user also asks about live device state or control, defer to voltra-device-status or voltra-device-training respectively.