# Xunji Training Open API

> Securely read, export, normalize, summarize, cache, and write back Xunji (训记) training records through the official LLM Open API v2. Use when the user asks to import, export, inspect, organize, analyze, sync, or modify 训记 training data.

- Skill: `babyracoonbbq/xunji-training-open-api` (Agent Skill, multi-file: 6 files)
- Install (CLI): `npx skillmds@latest add babyracoonbbq/xunji-training-open-api`
- Raw SKILL.md: https://api.skillmd.com/api/skills/babyracoonbbq/xunji-training-open-api/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: AI & ML
- Author: BabyRacoonBBQ (https://skillmd.com/u/babyracoonbbq)
- Updated: 2026-09-22
- Page: https://skillmd.com/skills/babyracoonbbq/xunji-training-open-api

---


# 训记训练数据 Open API

Use the official v2 API for training records only. Read `references/api.md` before the first API operation in a task.

## Mandatory safeguards

- Call the API only when the user explicitly asks to read, export, organize, analyze, sync, import, or write training data.
- Read authentication only from `XUNJI_API_KEY`. Never print, log, cache, embed, or pass it in a body/query string.
- Cache by `datestr`. Reuse cached results and do not issue duplicate reads for the same date. Choose light or full mode before the first call.
- Enforce the 90-second per-training-day read interval. On `too frequent`, report the server retry time and wait; do not loop.
- Remove any returned field named `key` before displaying or caching data.
- Use Chinese movement names only for writes. Never send an internal movement key.
- If a movement name is uncertain, consult `https://github.com/Foveluy/Xunji-movements` and select an exact Chinese name. Do not invent one; ask the user when ambiguity remains.
- Never perform a real write in the same turn that first proposes the change. Show a concise change summary and wait for explicit user confirmation.

## Read workflow

1. Decide whether light data is sufficient. Use full data when the request needs unchecked sets, RPE, notes, completion feelings, left/right weights, actual duration, or detailed composite sets.
2. Run:

```powershell
python scripts/xunji_open_api.py read --date 2026-04-02
python scripts/xunji_open_api.py read --date 2026-04-02 --full
```

3. Treat `res.trains` as the training list. Preserve `localid`, `start`, and `end` when preparing updates.
4. Parse record-style metrics from `sets[].metrics`. Composite sets may contain child movements in `sets[].items[]`.
5. Use the cached response for all subsequent work on that date.

The default cache directory is `~/.codex/cache/xunji-training-open-api/`. Override it with `--cache-dir` only when task isolation requires it.

## Write workflow

1. For an existing training, read full data first and preserve unchecked sets plus `localid`, `start`, and `end` unless the user explicitly changes time.
2. Build a JSON payload containing only the training records being created or updated. Omission never means deletion.
3. Validate and summarize offline:

```powershell
python scripts/xunji_open_api.py summarize --file proposed-trains.json
```

4. Show the user the date, title, created/updated records, movement changes, set changes, and any time changes. Wait for explicit confirmation.
5. After confirmation, run the server dry run first:

```powershell
python scripts/xunji_open_api.py upsert --file proposed-trains.json
```

6. If the dry run succeeds and still matches the approved summary, apply exactly that payload:

```powershell
python scripts/xunji_open_api.py upsert --file proposed-trains.json --apply --confirmed
```

7. Use the normalized response returned by the server as the new cache state.

## Write constraints

- Send at most 4 trainings, all for the same `datestr`.
- Send at most 15 movements per training and 20 sets per movement.
- Include `localid` to update; omit it to create. Do not delete old trainings merely because they are absent from the payload.
- When `localid` is present, retain `start` and `end` unless the user approved a time change.
- Each simple set must include at least one of `weight`, `weight_kg`, `reps`, `time`, `duration_s`, or `selfWeight`.
- Preserve incomplete sets with `done: false`.
- Never include secrets or authorization fields in a payload file.

## Errors

- `apikey missing` or `apikey invalid`: ask the user to copy or regenerate the key in 训记, then configure `XUNJI_API_KEY` locally.
- `仅VIP可用`: explain that the account requires the relevant membership permission.
- Unknown movement: stop and ask for confirmation after checking the standard Chinese movement list.
- Validation failure: do not call the API; correct the draft first.


