跳到正文
cccskills
免费在 GitHub 公开

add-exercise

Add a new built-in exercise to Liftosaur end-to-end — image (gymvisual.com → S3), catalog registration, description page, and the LLM/MCP exercise list. Use when adding one or more built-in exercises to the app catalog.

中文简介正在准备中。当前显示原文说明。

astashov/liftosaur星标 761(GitHub 761 + cccskills 0)
集成工具YouTubeAWS

实测评分 未实测

查看安装方法

包含的文件(1)

  • SKILL.md8.1 KB

SKILL.md(原文)

安装前可以查看交给 AI 代理的指令内容。

Add a Built-in Exercise to Liftosaur

Add the exercise(s): $ARGUMENTS

A built-in exercise touches six places. Do them in order. Worked example throughout: Nordic Curl, id nordicCurl, equipment bodyweight, image key nordiccurl_bodyweight.

Naming conventions (get these right first)

  • IExerciseId — camelCase, e.g. nordicCurl. It's a free v.string() (src/types.ts), so there is no enum/picklist to update. Pick an id that is NOT exactly 8 lowercase letters (avoids the theoretical collision space with random custom-exercise ids).
  • Display name — Title Case, e.g. Nordic Curl.
  • Equipment — one of the equipments in src/types.ts (bodyweight, barbell, dumbbell, cable, leverageMachine, band, kettlebell, smith, ezbar, trapbar, medicineball).
  • Image / file key — lowercased id + "_" + equipment, e.g. nordiccurl_bodyweight. Used for the S3 image filename, the exerciseImage.ts sets, and the exercises/*.md filename.

Step 1 — Image (gymvisual.com → S3)

Illustrations come from purchased gymvisual.com assets, cropped and uploaded to the images S3 bucket by src/imageExtractorGymVisual.ts.

If the exercise reuses an existing exercise's image (e.g. a slight variant): skip S3 entirely and instead set reuseImageFrom: { id, equipment } on the exercise entry in Step 2. Then skip to Step 2.

Otherwise, get a new image (manual, human-in-the-loop — costs money):

  1. Find the image fast. gymvisual names exercises differently than we do, so don't browse by hand — search its catalog across a few synonym terms:
    npx ts-node ./scripts/gymvisual_search.ts "nordic curl" "hamstring curl" "glute ham raise"
    
    (Run ts-node directly, not npm run r — npm strips quotes and splits multi-word terms.) It prints candidate exercises grouped across formats, illustrations first with preview image URLs. Only the illustrations category yields the transparent multi-pose PNG the extractor needs; exercises that exist only as gif/video are flagged as not-extractable. Pick the right illustrations/<id>-<slug>.html product, eyeballing the preview: image. --all lists gif/video-only matches; --max=N widens the scan per term.
  2. Ask the user to buy + download that illustration PNG on gymvisual.com. gymvisual illustrations are a multi-pose sheet.
  3. Have the user tell you the pose index (boxIndex, 0-based, counted left-to-right) to use as the single-pose thumbnail.
  4. Arrange a source directory: <src>/<id>_<equipment>_<boxIndex>/ containing the downloaded file whose name matches /_medium/ (e.g. nordiccurl_bodyweight_2/xxx_medium.png).
  5. Prereqs: ImageMagick convert on PATH, and AWS credentials with write access to the images bucket.
  6. Run:
    npx ts-node src/imageExtractorGymVisual.ts <src-dir> <dest-dir>
    
    It crops the single pose to 400x600 (→ exercises/single/small/) and the combined sheet to 800x600 (→ exercises/full/large/), uploads both to S3, then prints "Available small images" and "Available large images" arrays.
  7. Copy those printed arrays into src/models/exerciseImage.ts, replacing the availableSmallImages and availableLargeImages set contents (entries are lowercased id_equipment). At minimum the new nordiccurl_bodyweight must appear in both sets — ExerciseImageUtils_exists gates whether the app shows an image.

Step 2 — Register the exercise (src/models/exercise.ts)

Add to allExercisesList (keep it alphabetically near its neighbors):

nordicCurl: {
  id: "nordicCurl",
  name: "Nordic Curl",
  defaultWarmup: 10,
  defaultEquipment: "bodyweight",
  types: ["lower"],
  startingWeightLb: { value: 0, unit: "lb" },
  startingWeightKg: { value: 0, unit: "kg" },
},
  • types — subset of upper/lower/push/pull/legs/core. Copy from the closest analogous exercise.
  • startingWeight* — 0 for pure bodyweight; otherwise a sane starting load matching similar exercises.
  • Add reuseImageFrom: { id: "...", equipment: "..." } here if you skipped Step 1.

Add to the metadata record (same file, keyed by id):

nordicCurl: {
  targetMuscles: ["Hamstrings"],
  synergistMuscles: ["Gastrocnemius", "Gluteus Maximus"],
},

targetMuscles / synergistMuscles must be exact literals from the availableMuscles list in src/types.ts (typed as IMuscle) — inventing a name is a type error. The allowed values:

Adductor Brevis, Adductor Longus, Adductor Magnus, Biceps Brachii, Brachialis, Brachioradialis, Deltoid Anterior, Deltoid Lateral, Deltoid Posterior, Erector Spinae, Gastrocnemius, Gluteus Maximus, Gluteus Medius, Hamstrings, Iliopsoas, Infraspinatus, Latissimus Dorsi, Levator Scapulae, Obliques, Pectineous, Pectoralis Major Clavicular Head, Pectoralis Major Sternal Head, Quadriceps, Rectus Abdominis, Sartorius, Serratus Anterior, Soleus, Splenius, Sternocleidomastoid, Tensor Fasciae Latae, Teres Major, Teres Minor, Tibialis Anterior, Trapezius Lower Fibers, Trapezius Middle Fibers, Trapezius Upper Fibers, Triceps Brachii, Wrist Extensors, Wrist Flexors

(Check src/types.ts for the current source of truth.) When unsure which muscles apply, copy from the metadata entry of the most analogous exercise.

Step 3 — Description page (exercises/<id>_<equipment>.md)

Filename is lowercased: exercises/nordiccurl_bodyweight.md. Format:

---
video: "<youtube-id>"
description: "One-sentence summary of the exercise and what it trains."
---

## Starting Position

1. ...

## Movement

1. ...

## Key Points

- ...

<!-- howto -->

### Set Up Your Position

Plain-prose step.

### Execute the Movement

Plain-prose step.
  • video — the YouTube video id only (the abc123XYZ part, not the full URL). Find a real, good demonstration video; do not fabricate an id.
  • Everything before <!-- howto --> is the form guide; everything after is parsed into ### Heading + prose steps (see scripts/build-exercises.ts).
  • Match the tone/quality of existing files (exercises/pushup_bodyweight.md, exercises/pistolsquat_bodyweight.md) and the writing guidance in .claude/commands/describe-technique.md.

Then regenerate the compiled descriptions (never hand-edit the generated file):

npm run build:exercises

This rewrites src/models/exerciseDescriptions.ts, keyed by nordiccurl_bodyweight.

Step 4 — LLM/MCP exercise list (llms/exercises.md)

Add the display name to llms/exercises.md (this manually-maintained list is compiled to src/generated/exercises.ts by scripts/build-markdown.js and surfaced to the LLM/MCP via lambda/mcp/reference.ts). Match the existing formatting, including per-equipment variants (Name, Equipment) if the exercise ships with more than its default equipment. The regeneration runs as part of the normal build.

Step 5 — Verify

  • npx tsc --noEmit — no type errors.
  • Exercise appears in the picker (search its name).
  • Its detail/how-to page renders the image, description, video, and how-to steps.
  • If you added several exercises, re-run the exercise unit tests: npx mocha --require ts-node/register test/exercise.test.ts.

Name-collision safety (already handled in code — do not re-implement)

Users often create custom exercises to fill catalog gaps. When a new built-in shares a name with a user's custom exercise, resolution prefers the custom one, so existing programs/history never silently re-point to the new built-in. This is enforced in Exercise_findIdByName / Exercise_findByNameAndEquipment (src/models/exercise.ts, custom-index checked before nameToIdMapping) and covered by test/exercise.test.ts ("custom exercise wins over built-in on name collision"). You don't need to do anything per-exercise — just be aware that picking a display name that matches an existing custom exercise is safe by design.

评价

还没有评价。欢迎分享你的使用感受。

评论

无需登录即可发表。欢迎分享使用感受、提问,或说明在哪些环境下无法运行。

还没有评论。来写第一条吧。

提交后会立即公开。请勿填写邮箱、电话等个人信息。URL 最多 2 个。

0 / 1000 字

此表单受 reCAPTCHA 保护,适用 Google 的隐私权政策和服务条款。

同一仓库的技能

add-page

免费

Add a new server-rendered page to the Liftosaur website. Use when creating new public-facing pages with routing, SSR, and client hydration.

中文简介正在准备中。当前显示原文说明。

astashov/liftosaur7612026年10月26日 更新

Create a 30%-off coupon for an affiliate or creator on iOS and Android, and draft the reply that tells them how to use it. Use when asked to create, set up or send a coupon or promo code for an affiliate, influencer or creator.

中文简介正在准备中。当前显示原文说明。

astashov/liftosaur7612026年10月26日 更新

Interactively investigate a production Rollbar error. Accepts an occurrence id, item id, item counter, or Rollbar URL. Fetches the error data, assesses how widespread it is, drills into affected users (events, logs, storage, captured state), and works with the developer toward a fix or ignore decision. Use for collaborative debugging; use /fix-rollbar for a straight fetch-and-fix of a single occurrence.

中文简介正在准备中。当前显示原文说明。

astashov/liftosaur7612026年10月26日 更新

Investigate a user-reported issue using server logs, user events, storage snapshots, and Rollbar. Use when given a user id or email plus an issue description (e.g. from a support email).

中文简介正在准备中。当前显示原文说明。

astashov/liftosaur7612026年10月26日 更新

feature

免费

Build a feature end to end — decide worktree vs here, design the architecture and debate it with codex, get the user's approval on a one-pass-readable plan, state the API/state contract, implement with visible diffs, then run two codex reviews (bugs + architecture) and document the result. Use when asked to build/implement/add a feature or do a refactor that involves design decisions.

中文简介正在准备中。当前显示原文说明。

astashov/liftosaur7612026年10月26日 更新

Fix a production exception from Rollbar in an interactive Claude Code session. Fetches the occurrence data, analyzes the error, and either implements a fix or adds the error to the ignore list. Use when given a Rollbar occurrence ID.

中文简介正在准备中。当前显示原文说明。

astashov/liftosaur7612026年10月26日 更新

查看 astashov 的全部技能

报告此技能的问题