Beyond Cortex

VOLTRA Device Training

Safely operate all VOLTRA training modes through Cortex. Use when the user asks to enter a training mode (weight training, resistance band, damper, isokinetic, isometric, rowing, skiing), set load/resistance/velocity, start a rowing/skiing distance preset or Just Row, turn load on, unload, finish training, configure chains/eccentric, enter cable-length mode, switch/change weight units (lbs/kg), pair or unpair Twin devices, manage session templates (create/update/delete/list), manage custom workout actions, or create/apply custom curves. **Operation only** — if the user is asking what a mode is or wants a recommendation, use `voltra-training-modes` instead. For pure device-state inspection (battery, mode, connection), use `voltra-device-status`. This skill controls VOLTRA's built-in Rowing and Skiing modes only; Concept2 Rowing/Ski history and combined reports belong to `voltra-workout-data`.

Use Cortex's built-in guards as hard stop signals. The device may block commands when it is off the dock, not in a training mode, or the cable is not at zero. When that happens, report the exact reason and stop.

Twin pairing is supported (voltra twin pair / twin status / twin unpair). When topology is Twin (twinConnected, pairing, or degraded), do not enter customCurve or sled pull: set-mode customCurve and custom-curve apply are rejected until unpair; Cortex has no sled-pull training command. Twin can use weightTraining, resistanceBand, damper, isokinetic, isometric, rowing, and skiing. Custom-offset load is still out of scope. All listed single-device training modes remain supported, including Isometric (set-mode isometric then voltra load). Rowing and skiing: set-mode rowing|skiing plus rowing-start / skiing-start. set-auto-unload is supported. Isokinetic is supported; do not confuse it with Isometric. Chains and eccentric support both absolute values and integer percentages; Mountain chains are available through set-chain-mode mountain when the device advertises the capability. Note: auto-load, cancel-auto-load, safety-check, and recording are not supported commands — do not invent them.

Twin Target Rule

voltra twin pair and voltra twin connect are the setup commands. When exactly two devices are already connected, omit both selectors and the first-connected device becomes master. If either selector is provided, provide both --master <MASTER> --slave <SLAVE>. After a Twin is confirmed, the connected logical master is the default target for status, finish-training, unload, twin status, voltra stream, and twin unpair: omit --device-id and --master in the normal flow. The unified voltra stream command automatically emits the Twin v1 stream for a confirmed Twin. Use --device-id <MASTER> with voltra stream only to disambiguate multiple connected sessions or pairs. Never pass the slave ID to a Twin training, finish, status, stream, or unpair command. For a Twin status snapshot, use voltra status --json or select the master; the slave has no independent live status session while paired. After unpair, the devices are independent again and may be selected separately with --device-id.

Mode Context Rule (Critical)

Always check the current training mode before issuing any load/resistance/velocity command. Different modes use different commands for the same user intent. A request like "set weight to 50" or "change load to 30" must be routed to the correct command based on the active mode:

Current ModeUser Says "set weight/load to X" → Use
weightTrainingvoltra set-weight <n>
resistanceBandvoltra set-resistance-band <n>
dampervoltra set-damper <n> (level, not load)
isokineticvoltra set-isokinetic-velocity <n> (velocity, not load)
noneTell the user to enter a training mode first

Check the mode first. Run voltra status --json and read trainingMode. If unsure which mode is active, refresh status before issuing any control command. Do not use set-weight unless the device is confirmed to be in weightTraining mode.

Physical Risk Acceptance (Required Before Load)

The voltra load command engages the VOLTRA motor and applies physical force. It will be blocked until the user explicitly accepts the physical risk:

voltra config accept-physical-risk --json

Or set the environment variable:

$env:VOLTRA_ACCEPT_PHYSICAL_RISK="true"

This is a one-time acceptance. If voltra load returns "Physical risk not accepted", guide the user to run the command above. Do not retry load until acceptance is confirmed.

Command Prerequisites

Some settings commands require the device to be in a safe state. When a command is rejected, read the error message and fix the state before retrying:

If the error saysThen first
"Turn weight off before..."voltra unload --json
"Finish the current training mode before..."voltra finish-training --json
"not docked" / "cable not zero" / "workout mode none"Report the exact reason to the user. Do not guess a workaround.

CRITICAL — set-weight-unit always requires unload + finish-training first. This is non-negotiable. If the user asks to switch units ("switch to kg", "use kg", "use lbs", "change to lbs"), you MUST run unload AND finish-training before set-weight-unit. Do NOT attempt set-weight-unit while power is on or a training mode is active. Follow the flow below exactly:

Units and Input Conventions

Weight values default to pounds (lbs). set-weight, set-chains, and set-eccentric all accept bare numbers as lbs. To input in kilograms, add the --unit kg flag — Cortex converts the value to lbs before sending it to the device:

voltra set-weight <lbs> --json              # lbs input
voltra set-weight <kg> --unit kg --json     # kg input → converted to lbs
voltra set-chains <kg> --unit kg --json     # kg input → converted to lbs
voltra set-chains <percent> --percent --json # integer percentage, 0..300
voltra set-eccentric <percent> --percent --json # integer percentage, -100..300

set-weight-unit is NOT an input conversion flag. It sets the device's global display preference (lbs or kg) — it affects all modes, not just weight training. It does not convert the values you type.

--percent is an alternative input interpretation for set-chains and set-eccentric; it cannot be combined with --unit kg. The command enables percentage-force interpretation before writing the value. An absolute chains/eccentric command switches back to lbs interpretation.

Prerequisites for set-weight-unit: the device must be unloaded (power off) and not in a training mode (none). If power is on or a mode is active, the device will reject the command. The correct flow:

voltra unload --json                        # turn power off
voltra finish-training --json               # exit to mode none
voltra set-weight-unit <lbs|kg> --json      # now safe to change
voltra set-mode <mode> --json               # e.g. weightTraining
voltra set-weight <lbs> --json              # set new weight
voltra load --json                          # turn power on

Example:

voltra set-weight-unit <lbs|kg> --json   # tell the device display preference
voltra set-weight <lbs> --json           # still lbs input — set-weight-unit does not convert this

Use --unit kg for input conversion. Use set-weight-unit to change the device's preference.

Other units used across modes:

UnitWhereExample
lbs (pounds)weight, chains, eccentric, resistance bandset-weight 60
kg (via --unit kg)weight, chains, eccentric input conversionset-weight 22.5 --unit kg
m/s (meters per second)isokinetic velocity inputset-isokinetic-velocity 0.5 → 0.500 m/s (sent to device as 500 mm/s)
cm (centimeters)resistance ROM length, cable positionset-resistance-rom-length 180
secondsauto-unload hold-still triggerset-auto-unload 3 12
reps (count)auto-unload rep-count triggerset-auto-unload 3 12
level (1-10, dimensionless)damperset-damper 4

Baseline Workflow

Every training flow starts with these steps:

  1. Connect or reconnect:
voltra reconnect --json

If the user named a device:

voltra connect <device-id-or-name> --json
  1. Refresh and inspect state:
voltra refresh <scope> --json   # e.g. all, epStatus
voltra status --json
  1. After changes, verify:
voltra refresh <scope> --json   # e.g. all, epStatus
voltra status --json

Stop and Unload

load and unload work in any training mode — they apply whatever the current mode has configured (weight, resistance band, damper level, isokinetic velocity).

Use these when the user asks to stop or when a control flow must leave the device safe:

voltra unload --json
voltra finish-training --json

Report the resulting mode and power state from voltra status --json.


Weight Training

Use only when the user asks for weight training:

voltra set-mode <mode> --json   # e.g. weightTraining

If this says to place the device on the dock, stop. Do not retry until the user says the device is on the dock.

Set weight:

voltra set-weight <lbs> --json
voltra set-weight <kg> --unit kg --json

Load and unload work in any training mode (see Stop and Unload above).

If loading is blocked, stop and report the reason. Common meanings:

  • not-docked: the VOLTRA unit is not seated on its dock. Training requires the unit to be physically mounted on the dock.
  • workout-mode-none: enter a training mode first.
  • cable-not-zero: the cable is not at its fully retracted starting position. For safety, the cable must be at zero before the device will engage power.

The cable-not-zero block is a safety mechanism. Do not try custom-offset load, lower-level SDK calls, or repeated retries.

voltra load --force override (advanced, safety-sensitive): Cortex provides --force to bypass the cable-zero check and apply force immediately at the current cable position via apply_force_immediately. This is intended for Isometric holds at a specific joint angle, or advanced setups where returning the cable to zero is not practical. It applies force at a non-zero position — do not use it unless the user explicitly asks for it and understands the risk, and never use it as a workaround for a cable-not-zero block the user did not expect. Default behavior: report cable-not-zero and stop; mention --force only when the user's intent (e.g. Isometric at a set angle) clearly calls for it.

Weight Selection

  • Use the user's requested weight when given.
  • If the user asks for a light/default weight and gives no value, use 10 lbs.
  • Do not choose aggressive loads. Ask the user for a number when the request is ambiguous and physical safety matters.

Weight Training Controls

CommandValueMeaning
set-weight <n>lbs (default) or kg with --unit kgTarget load. Ranges are device-derived; run voltra status to see limits.
set-chains <n>lbs (default) or integer percentage with --percentExtra resistance that increases as the cable extends. Percentage range is 0..300.
set-eccentric <n>lbs (default) or integer percentage with --percentAdditional load applied during the eccentric (return) phase. Percentage range is -100..300.
set-inverse-chains on|off—When on, chains resistance decreases as the cable extends (inverse of normal).
set-chain-mode standard|inverse|mountain—Selects the chain curve. Mountain requires device support; inverse and Mountain are mutually exclusive.
set-auto-unload <s> <r>seconds, rep countAuto-unload is triggered by either condition: the user holds still for <s> seconds, OR <r> reps are completed. Both conditions are independent — whichever happens first triggers the unload. Example: set-auto-unload 3 12.

Examples:

voltra set-chains 125 --percent --json
voltra set-eccentric -50 --percent --json
voltra set-chain-mode mountain --json
voltra set-chain-mode standard --json  # clear inverse/Mountain

Cable Zero and Cable Length

The VOLTRA unit has a cable. The cable zero is the cable's fully retracted, starting position. For safety, the device will not allow training to begin unless the cable is at zero (cable-not-zero block in the load step).

Cable length mode lets you preset a new zero position. For example, setting cable length to 10 cm means the cable stops at 10 cm out from the dock — that 10 cm becomes the new zero for subsequent training. This is used to pre-configure starting positions for specific exercises.

voltra check-cable-zero --json       # confirm cable is at zero
voltra cable-length <enter|exit> --json  # enter or exit cable-length adjustment mode

Always exit cable-length mode before resuming normal training commands.


Resistance Band

Primary load command: set-resistance-band — NOT set-weight. Even if the user says "set weight" or "change load", use set-resistance-band when the device is in resistanceBand mode.

First-version scope: only set-mode resistanceBand and set-resistance-band. All other resistance band sub-commands (set-quick-adjust, set-resistance-experience, set-resistance-mode, set-resistance-curve, set-resistance-by-rom, set-resistance-rom-length, set-resistance-metric) are excluded.

voltra set-mode <mode> --json   # e.g. resistanceBand
CommandValueMeaning
set-resistance-band <n>lbs (or kg with --unit kg)Target resistance in pounds. Supports --unit kg for metric input. Example: voltra set-resistance-band 22.5 --unit kg --json

Do not invent safe default resistance. Ask for a number unless the user explicitly says to use a light/default value.


Damper

Primary control command: set-damper — NOT set-weight. Damper uses level 1-10, not lbs.

First-version scope: only set-mode damper and set-damper. set-damper-metric is excluded.

voltra set-mode <mode> --json   # e.g. damper
CommandValueMeaning
set-damper <n>1–10 (dimensionless)Resistance level. 1 = lightest, 10 = heaviest.

Report Cortex validation errors as-is; do not guess supported level ranges.


Isokinetic

Primary control command: set-isokinetic-velocity — NOT set-weight. Isokinetic uses velocity in m/s (Cortex converts it to mm/s internally before sending to the device), not lbs.

First-version scope: only set-mode isokinetic and set-isokinetic-velocity. All other isokinetic sub-commands (set-isokinetic-metric, set-isokinetic-eccentric-mode, set-isokinetic-eccentric-velocity, set-isokinetic-eccentric-force, set-isokinetic-eccentric-overload) are excluded.

voltra set-mode <mode> --json   # e.g. isokinetic
CommandValueMeaning
set-isokinetic-velocity <n>m/sTarget cable velocity for the concentric (pulling) phase. Example: voltra set-isokinetic-velocity 0.5 --json (sent to device as 500 mm/s).

Ask for velocity values when ambiguous. Do not prescribe max-effort values.


Rowing & Skiing (Cardio)

Source boundary: This section operates the connected VOLTRA device's Cardio Rowing or Skiing mode. It is not a Concept2 controller and does not query Concept2 Logbook. If the user asks for rowing or skiing history without naming a source, use voltra-workout-data to resolve VOLTRA type 8 versus Concept2 Rowing or VOLTRA type 9 versus Concept2 Ski before acting.

Cardio modes share TrainingMode::Rowing (write value 3); rowing vs skiing is selected by the cardio activity parameter (0=rowing, 1=skiing).

Two-step model — setting the mode is not the same as starting a workout:

  1. set-mode rowing|skiing — switches the device into cardio mode and optionally configures resistance / simulated wear level. The device is in cardio mode but no target distance is set yet, so it will not start a timed/distance workout.
  2. rowing-start <preset> / skiing-start <preset> — writes the target-distance preset. This is what actually starts the workout. Without this step the device enters cardio mode but has no goal to row/ski toward.
voltra set-mode rowing --resistance 5 --json          # enter rowing mode, set resistance
voltra rowing-start 500 --resistance 5 --json          # start a 500m rowing workout

Argument order matters — put the positional value first, then flags. rowing-start/skiing-start take a positional <preset> (e.g. 500, just-row); set-mode takes a positional <mode> (e.g. rowing). Write voltra rowing-start 500 --resistance 5 --json, not voltra rowing-start --resistance 5 500 --json. Both orders parse (clap accepts interspersed flags), but preset-first is the documented form and avoids ambiguity with future options.

Presets

<preset> is one of (meters):

ValueMeaning
just-rowJust Row — no target distance; device reports 500m splits.
5050 m
100100 m
500500 m
10001,000 m
20002,000 m
50005,000 m

Commands

CommandValueMeaning
set-mode rowing|skiing—Enter cardio mode. --resistance <1..10> applies to both (written 0..9). --wear-level <1..10> applies to rowing only (written 0..9, simulated wear).
rowing-start <preset>preset enumStart a rowing workout at the given target distance (or Just Row). Supports --resistance, --wear-level, device selector.
skiing-start <preset>preset enumStart a skiing workout at the given target distance (or Just Row). Supports --resistance, device selector. No --wear-level (skiing has no simulated wear).

rowing-start / skiing-start handle mode entry internally — if the device is not already in Rowing mode they will switch it, set the cardio activity, apply optional resistance/wear, then write the preset. You do not need to run set-mode first, but running set-mode to pre-configure resistance/wear and then rowing-start <preset> to begin is also valid.

To stop a cardio workout and exit the mode, use voltra finish-training --json (returns to none).


Custom Curve (Cloud API)

Custom curves define non-linear force profiles applied to training modes. Managed via custom-curve commands — no device connection required (pure Cloud API, no BLE/dock/cable-zero).

Same API key resolution as workout commands. For full parameter tables and response shapes (validate/encode/create/update/delete/apply flags, JSON output schema), see references/command-reference.md → Custom Curves.

Commands

CommandPurpose
voltra custom-curve listList all saved custom curves
voltra custom-curve validateValidate curve parameters locally without saving
voltra custom-curve encodeEncode parameters to controls/path without saving
voltra custom-curve createCreate a new custom curve
voltra custom-curve update <id>Update an existing curve
voltra custom-curve delete <id>Delete a curve
voltra custom-curve apply <id>Pull curve from cloud and send to connected device (requires BLE connection)

Points Format

Control points use normalized [0, 1] values in semicolon-separated x,y pairs:

"x1,y1;x2,y2;x3,y3;..."
  • ; separates each point; , separates x and y within each point
  • x = fraction of ROM (0 = start, 1 = full ROM)
  • y = fraction of force range (0 = min-force, 1 = max-force); y increases with force (math/bottom-origin coordinates, no flip)

Wrong formats that will fail: space-delimited, comma-only (no ;), JSON arrays, or absolute units instead of [0,1] fractions.

Example — ROM 80 cm, force 10–150 lbs, 4 control points:

voltra custom-curve create \
  --name "My Curve" \
  --rom-cm 80 \
  --min-force 10 \
  --max-force 150 \
  --points "0,0.1;0.3,0.4;0.7,0.8;1,1" \
  --dry-run --json

Constraints

  • --min-force must be ≥ 5
  • At least 2 x,y pairs; x and y must be in [0, 1]
  • Name must be unique per account
  • Optional: --cable-offset-cm (cm), --dry-run (preview only)

Unit trap on backend payload: the extraConfig block returned by encode / create has inconsistent units by backend design — cableOffset is in mm, while endCableLength (= ROM) is in cm. Cortex handles the cm ↔ mm conversion at the boundary (user --cable-offset-cm ↔ backend cableOffset). Do not assume cableOffset and endCableLength share a unit when reading the raw payload.

Safe Workflow

voltra custom-curve validate --rom-cm <cm> --min-force <n> --max-force <n> --points "<points>" --json
voltra custom-curve encode --name "<name>" --rom-cm <cm> --min-force <n> --max-force <n> --points "<points>" --json
voltra custom-curve create --name "<name>" --rom-cm <cm> --min-force <n> --max-force <n> --points "<points>" --dry-run --json
# inspect validate response, then drop --dry-run to save

What to check in validate response (do not stop at valid: true):

FieldMeaning
valid: trueGeometry passed basic range checks. Still inspect the fields below.
editAllowed: trueRequired to be able to create / update this curve. false means the backend will reject writes.
inflectionCount ≤ maxInflectionsToo many inflections will block creation.
maxSlope ≤ maxSlopeLimitSlope too steep will block creation.
minIntervalCm ≥ minIntervalRequiredCmControl-point spacing below the minimum will block creation.
issues[]When valid: false, this lists the specific problems.

Only proceed to create / update when all of the above are within limits.

Apply (Device Command)

voltra custom-curve apply <curve-id> fetches a saved curve from the cloud and sends it to the connected VOLTRA device. Unlike other custom-curve commands, apply requires an active BLE connection and is routed through the daemon.

voltra custom-curve apply <curve-id> --json
voltra custom-curve apply <curve-id> --temporary --json

What it does:

  1. Fetches the curve (with its path / extraConfig) from the cloud API
  2. Switches the device to customCurve (Professional) training mode
  3. Sends the Bezier curve bytes to the device
  4. Sets cable offset if configured (or resets it); --temporary marks the offset as non-persistent

Flags:

FlagNotes
<curve-id>Required. Numeric cloud curve ID (from custom-curve list)
--temporaryOptional. Cable offset is temporary (not saved to device persistent storage)
--device-id <id>Optional. Device selector (same as other device commands)
--timeout-ms <ms>Optional. Connection/command timeout

Prerequisites: Device must be connected (voltra connect or voltra reconnect) and not in Twin. If voltra status topology is Twin, unpair first; Cortex rejects Twin custom-curve apply and Twin set-mode customCurve. The command handles mode switching internally — no need to run set-mode first.

Output (JSON):

{
  "applied": true,
  "curveId": 42,
  "name": "My Curve",
  "count": 3,
  "endX": 1200,
  "forceLowerBound": 50,
  "forceUpperBound": 250,
  "cableOffsetCm": 12
}

Guardrails

  • Preserve user-provided geometry; do not invent force curves
  • Always validate → encode/--dry-run → create/update when uncertain
  • Do not manually construct controls or path arrays; the engine generates them from --points
  • delete is idempotent — deleting a non-existent ID still returns success
  • apply requires a live BLE connection; do not call it in cloud-only workflows
  • apply and set-mode customCurve are blocked while Twin is paired; unpair first
  • For full parameter tables and response shapes, see references/command-reference.md

Guardrails

  • Treat Cortex errors and blocked messages as authoritative.
  • Never loop on set-mode, set-weight, load, or equivalent mode-entry commands after a blocked response.
  • If voltra load is blocked by physical risk acceptance, direct the user to voltra config accept-physical-risk or set VOLTRA_ACCEPT_PHYSICAL_RISK=true. Do not retry until accepted.
  • Do not use auto-load or cancel-auto-load; the current Cortex version should remove them if present.
  • set-auto-unload is allowed only when the user asks for auto-unload behavior.
  • Do not add a generic 20% low-battery block for training. Cortex does not enforce a low-battery training gate; if the device rejects a command for low battery, report Cortex's message as-is.
  • Do not issue training-control commands unless the user asked for device control.
  • Do not treat cached known-device storage as live state.
  • Twin training is allowed for weightTraining, resistanceBand, damper, isokinetic, isometric, rowing, and skiing. Never switch Twin into customCurve or sled pull; if Cortex says Twin does not support that mode, unpair instead of retrying.
  • If a blocked or failed command persists and the cause is unclear, load voltra-cli-troubleshooting for systematic diagnosis.
  • For device state inspection (battery, mode, connection), use voltra-device-status.
  • For first-time setup guidance, use voltra-getting-started.
  • For the complete Cortex command reference, see references/command-reference.md. Read it when you need: Twin pairing/stream (twin status/pair/connect/unpair/stream), daemon management commands (daemon status/stop), logs (logs path/tail/upload/clear), workout History upload queue commands, skills management (skills add/update/list/remove), config & identity (config set-api-key/show/clear-api-key/accept-physical-risk, whoami, doctor, ble doctor), full session / custom-curve parameter tables, or response shapes for any command.

Session Templates (Training Plans)

Session templates define reusable workout training plans. Managed via voltra session * commands — no device connection required (Cloud API only). See references/command-reference.md → Session Templates for full parameter tables.

Scope boundary: This skill owns session template CRUD (create/update/delete/rename/touch/list/detail). For analyzing past workout history (sets, reps, volume, trends), use voltra-workout-data — do not query workout records from here.

Cortex only supports creating/managing session templates — it does not execute session training. All CRUD, rename, and touch operations happen in the cloud. However, following a session template's exercise sequence for actual training (guided workouts, auto-switching exercises/sets/weight) requires the Beyond+ App, which currently only supports this on iOS. Android does not yet support session training execution.

Mandatory reading before generating session JSON

Before writing any create payload, you MUST read references/session-schema-reference.md. It is the authority for Session Agent Contract v1, including mode-specific ranges, Set override semantics, and cross-field rules. Use references/session-template-snippets.md only after reading the contract. Run voltra session validate --from <path> before upload; backend validation remains final.

Hard rules (silent-failure guards)

These are the rules that look optional but silently break the template. They are non-negotiable when generating session JSON:

  • Agent v1 create only allows blockType=1..2 and workoutMode=1..4. Do not generate other backend modes for this endpoint.
  • Use consecutive, unique, 1-based itemGroupPosition and itemDetails[].position. Zero, duplicates, and gaps are invalid.
  • Always include sessionConfig, actionModeConfig, and modeConfig. Blocks, Items, and Sets must be non-empty.
  • Never emit null for non-null configuration scalars. Generate the canonical defaults from the schema reference even though the current Cortex client materializes omitted defaults before upload. The backend may persist omitted fields as null, and older Cortex versions do not protect against that.
  • Never emit 0 for eccentricValue, chainsValue, or inverseChainsValue; use null when disabled. Never set both Chains fields positive. At Set level, all-null means inherit; any non-null value overrides the atomic Eccentric/Chains/Inverse Chains group.
  • baseValue is mode-dependent. Weight 5..230, Resistance Band 15..230, Damper 1..10, Isokinetic 10..200. Resolve actionId via voltra actions list/get; use 33 only when the user explicitly wants the generic/free exercise fallback.
  • Direction must match Hand Mode. Bilateral uses handMode=2 and direction=0; Unilateral uses handMode=1 and direction=1 or 2.
  • Drop Set Sets use tag=2, only with Weight Training, and never inside a Circuit. Target-Reps Unload and Zero-Position Unload must be enabled or disabled together; intermediate Set rest is 0.
  • Twin create payloads use Bilateral direction, disable Assist, and omit Isokinetic Eccentric fields cleared by the Twin flow. connectionMode=1 means two-device execution, not an ordinary bilateral exercise.
  • Update payload only accepts title, sessionConfig, blockList, connectionMode. Do not send accountRole, label, originSessionId, blockId, or itemId on update. Send the full rebuilt structure; partial item updates are not supported.

Drop set vs circuit: Drop Set Sets use tag=2 inside a Normal block; a Circuit uses blockType=2 and cannot contain Drop Sets. A session may mix them across separate blocks.

CommandPurpose
voltra session listList all session templates
voltra session detail <id>Show full session details
voltra session validate --from <path>Validate an Agent v1 create payload locally without an API key or upload
voltra session create --from <path>Create from JSON file
voltra session update <id> --from <path>Update from JSON file
voltra session delete <id> --yesDelete (requires --yes). Add --delete-records to also remove related training records — destructive, confirm with user first.
voltra session rename <id> <title>Rename session title
voltra session touch <id>Update active timestamp

All session commands use the standard API key resolution (--api-key flag → $VOLTRA_API_KEY → config).

Actions (Exercises)

Actions are the individual exercises available on VOLTRA. Each action has a numeric actionId used in session templates and workout data. Use voltra actions to discover actions and manage custom actions owned by the current account — no device connection required (Cloud API only).

CommandPurpose
voltra actions listList all actions (id, type, name)
voltra actions list --type-id 4Filter by body part (4=Chest)
voltra actions list --name curlSearch by name (case-insensitive)
voltra actions typesList action types (body parts)
voltra actions groupsActions grouped by body part
voltra actions get 33Look up action by id
voltra actions create --name "Bench Press" --type-id 4Create a custom action
voltra actions update 1024 --name "Incline Bench Press" --type-id 4Update an owned custom action
voltra actions delete 1024 --yesDelete an owned custom action after explicit confirmation

All action commands support --json for machine-readable output.

Custom action rules

  • --name is required for create and update. It must contain 1–50 characters with no leading or trailing whitespace.
  • --type-id defaults to Functional (10); values outside 1..=10 also fall back to 10.
  • Only custom actions owned by the current account can be updated or deleted. Never attempt to mutate built-in actions or another user's actions.
  • For rename-only updates, first run voltra actions get <id> --json and explicitly pass the existing typeId. Omitting --type-id resets the action to Functional (10).
  • Before delete, explain that referenced workout history will be reset to the default action list and obtain explicit user confirmation. Only then pass --yes.
  • Prefer --json and verify created/updated/deleted plus actionId in the result. Do not claim success from command intent alone.

Local Caches: Action catalog results are cached at ~/.voltra/actions.json (24h TTL). Successful custom-action writes invalidate that cache, so the next catalog read fetches current server data. voltra whoami refreshes ~/.voltra/user-preferences.json with the user's preferred units and body measurements; use this before generating sessions so loads/units match the account. voltra session detail uses the action cache to translate actionId → exercise name.

Common Action Types:

IDBody Part
1Whole Body
2Legs
3Back
4Chest
5Shoulders
6Biceps
7Triceps
8Core
9Forearms
10Functional

Default Action: actionId=33 (Free Exercises, type=Whole Body) is the fallback when no specific exercise is selected.