Skills DirectorySkills Directory
SkillsLearnSecurityCategoriesDocsCommunityBlog
Sign InSubmit Skill
Skills Directory

Security-tested agent skills for Claude, coding agents, and AI workflows.

Directory

  • Browse Skills
  • All Skills A–Z
  • Claude Skills
  • Claude Code Skills
  • Agent Skills
  • Categories
  • Submit a Skill

Learn

  • Learn Hub
  • Install Claude Skills
  • Write SKILL.md
  • Skills vs MCP
  • Directories Compared

Security

  • Security
  • Methodology
  • Secure Claude Skills
  • Security Badges

Company

  • About
  • Community
  • Blog
  • API Docs
  • Advertise

2026 Skills Directory. All rights reserved.

Back to skills

Iblai Api Studio Lms

BSecurity

Verify and operate the LMS side of an Open edX course built on Studio — the calls the lms.ibl.ai LMS app makes against the LMS API: enroll yourself or (as course staff) other users, check enrollment status, list a course's users, read the published outline and blocks as a user, read course details and the merged course metadata the catalog shows, and progress/grading as seen by users. Use after publishing to confirm what users see, to enroll test users, or when the user asks "is it in the cat...

15 stars
0 votes
0 copies
0 views
Added 9/20/2026
developmentpythonbashnodegitapi

Works with

api

Security Analysis

B88/100
criticalDownloads and executes remote scripts — classic supply chain attack

Scanned 9/20/2026

Install to Claude Code

$npx -y skills add iblai/vibe --skill iblai-api-studio-lms --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Iblai Api Studio Lms?

Add the live security badge to your README — it updates automatically with every re-scan.

Security grade badge for Iblai Api Studio Lms
[![Security: B — Skills Directory](https://www.skillsdirectory.com/api/skills/iblai-iblai-api-studio-lms/badge)](https://www.skillsdirectory.com/skills/iblai-iblai-api-studio-lms)

More formats (shields.io, HTML) on the badges page.

Download Zip
Files
SKILL.md
---
name: iblai-api-studio-lms
description: Verify and operate the LMS side of an Open edX course built on Studio — the calls the lms.ibl.ai LMS app makes against the LMS API: enroll yourself or (as course staff) other users, check enrollment status, list a course's users, read the published outline and blocks as a user, read course details and the merged course metadata the catalog shows, and progress/grading as seen by users. Use after publishing to confirm what users see, to enroll test users, or when the user asks "is it in the catalog / can students see it". Session auth via studio.env (LMS cookies).
metadata:
  kind: api
---

# iblai-api-studio-lms

The LMS app (`lms.ibl.ai`; test `lms.iblai.org`) renders a course from the
LMS API on `$LMS_URL` plus the ibl.ai catalog. This skill uses the LMS session
captured by `/iblai-api-studio-auth` to make the same calls, so you can prove a
build is visible, enroll users, and read what they will see. Nothing here
edits course content.

## Before you start

1. Preflight: `node .claude/skills/iblai-api-studio-auth/scripts/studio-login.mjs --check` prints two `ok`s (the second one is the LMS session used here); otherwise run **`/iblai-api-studio-auth`** first — do not attempt the calls below.
2. The course is published (`/iblai-api-studio-publish`) and its `enrollment_start` is in the past and before `start_date` (`/iblai-api-studio-settings`) — otherwise enrollment and outline reads legitimately return "not yet".
3. A course key.

## Auth & conventions

- **Base URL:** `$LMS_URL` (`https://learn.iblai.app`; test `https://learn.iblai.org`). LMS app: `$LMS_APP_URL`.
- **Auth:** LMS session cookies from `studio.env` (values single-quoted — strip them in any non-bash parser: `/iblai-api-studio-auth`).
- **Snippet:**
  ```bash
  set -a; . ./studio.env; set +a
  L=(-s -b "sessionid=$LMS_SESSION; csrftoken=$LMS_CSRF" -H "X-CSRFToken: $LMS_CSRF" \
     -H "Origin: $LMS_URL" -H "Referer: $LMS_URL/" -H "Accept: application/json" -H "Content-Type: application/json")
  ```
- `COURSE="course-v1:<org>+<number>+<run>"`; `CE` = the same URL-encoded (needed in **every query string**: `%3A` `%2B`).
- `$STUDIO_USERNAME` is the signed-in user; the same person must be enrolled to read blocks "as a user".
- Enrolling/unenrolling other people is outward-facing — confirm with the user first.

## Reads

- **GET** `/api/user/v1/me` → `{ "username" }` — session check.
- **GET** `/api/ibl/enrollment/enroll_status?course_id={CE}` → `{ "is_enrolled", "can_enroll", "invitation_only", "is_admin" }` for the signed-in user.
- **GET** `/api/enrollment/v1/enrollment/{username},{COURSE}` → `{ "created", "mode": "audit", "is_active", "course_details": { "course_id", "course_name", "enrollment_start", "enrollment_end", "course_start", "course_end", "invite_only", "course_modes": […], "pacing_type" }, "user" }` (own enrollment; `404` when not enrolled).
- **GET** `/api/ibl/v1/course_metadata?course_key={CE}` — the merged object the LMS app shows on the course page: all `/iblai-api-studio-settings` fields plus `display_name`, `course_price`, `advertised_start`, `display_organization`, `certificate_available`, `course_outline` (published tree). Catalog fields (`subject`, `tags`, `level`, …) read back from here prove the catalog sync.
- **GET** `/api/courses/v1/courses/{COURSE}` → Open edX course detail: `{ "id", "name", "org", "number", "start", "end", "enrollment_start", "enrollment_end", "pacing": "instructor" | "self", "short_description", "overview", "effort", "media": { "course_image": { "uri" }, "banner_image", "course_video": { "uri": "http://www.youtube.com/watch?v=…" } }, "blocks_url", "hidden", "invitation_only" }`. On some deployments this returns the shape with `null` values for a freshly built course (cache lag) — treat `course_metadata` above as the source of truth and use this only for `pacing`/`hidden`.
- **GET** `/api/ibl/completion/course_outline/{COURSE}?course_id={CE}` — the **published** outline as a user sees it, with completion: nested `{ id, block_id, type, display_name, lms_web_url, student_view_url, graded, start, has_score, effort_time, children: […] }` down to units. A unit missing here is unpublished or not yet released.
- **GET** `/api/courses/v2/blocks/?course_id={CE}&username={user}&depth=all&all_blocks=true&requested_fields=children,graded,format,due,type` → `{ "root", "blocks": { "<usage key>": { "id", "type", "display_name", "lms_web_url", "student_view_url", "children": […] } } }` — every visible block incl. components. `GET /api/courses/v2/blocks/{usage_key}?username={user}&depth=all` for one unit.
- **GET** `/api/course_home/progress/{COURSE}` → `{ "course_grade": { "percent", "letter_grade", "is_passing" }, "grading_policy": { "assignment_policies": [ { "type", "weight", "num_total", "num_droppable", "short_label" } ], "grade_range" }, "section_scores": [ { "display_name", "subsections": [ { "display_name", "assignment_type", "num_points_earned", "num_points_possible", "problem_scores", "url" } ] } ], "completion_summary", "enrollment_mode", "certificate_data" }` — grading policy and structure as graded.
- **GET** `/api/ibl/users/manage/roles/?username={user}` → `[ { "role", "org", "course" } ]` (course-staff / course-instructor / org-instructor …).
- **POST** `/courses/{COURSE}/instructor/api/get_students_features` (form-encoded, empty body; course staff only) → `{ "course_id", "students": [ { "id", "username", "email", "name", "enrollment_mode", … } ] }` — the enrolled users.

## Writes

- **POST** `/api/enrollment/v1/enrollment` `{ "course_details": { "course_id": "<COURSE>" } }` — enroll **yourself** (`mode` defaults to `audit`) → the enrollment object. Idempotent. `{ "course_details": {…}, "is_active": false }` unenrolls yourself. Passing `"user": "<other>"` needs global staff (`404` otherwise) — use the instructor route below.
- **POST** `/courses/{COURSE}/instructor/api/students_update_enrollment` (form-encoded; course staff/instructor) — enroll or unenroll other users by email or username. Confirm with the user first.
  ```bash
  curl "${L[@]:0:11}" -X POST "$LMS_URL/courses/$COURSE/instructor/api/students_update_enrollment" \
    --data-urlencode "identifiers=jdoe@example.com,asmith" --data-urlencode "action=enroll" \
    --data-urlencode "auto_enroll=true" --data-urlencode "email_students=false"
  ```
  → `{ "action": "enroll", "results": [ { "identifier", "before": { "user", "enrollment", "allowed", "auto_enroll" }, "after": {…} } ], "auto_enroll": true }`. `action=unenroll` removes. `identifiers` is comma/newline separated; unknown emails get `user: false` (with `auto_enroll=true` they are enrolled when they register). `email_students=true` sends the LMS enrollment email.

## Example

```bash
set -a; . ./studio.env; set +a
L=(-s -b "sessionid=$LMS_SESSION; csrftoken=$LMS_CSRF" -H "X-CSRFToken: $LMS_CSRF" \
   -H "Origin: $LMS_URL" -H "Referer: $LMS_URL/" -H "Accept: application/json" -H "Content-Type: application/json")
COURSE="course-v1:acme+DATA101+2026-T1"; CE=$(python3 -c "import urllib.parse;print(urllib.parse.quote('$COURSE',safe=''))")

curl "${L[@]}" -X POST "$LMS_URL/api/enrollment/v1/enrollment" -d "{\"course_details\":{\"course_id\":\"$COURSE\"}}" >/dev/null
curl "${L[@]}" "$LMS_URL/api/ibl/enrollment/enroll_status?course_id=$CE"          # {"is_enrolled":true,…}
curl "${L[@]}" "$LMS_URL/api/ibl/completion/course_outline/$COURSE?course_id=$CE" | python3 -c '
import sys,json
def walk(n,d=0):
    print("  "*d + n["type"].ljust(11), n["display_name"])
    for c in n.get("children",[]): walk(c,d+1)
walk(json.load(sys.stdin))'
ORG=${COURSE#course-v1:}; ORG=${ORG%%+*}
echo "LMS app URL: $LMS_APP_URL/platform/$ORG/courses/$COURSE"
```

## Notes

- **Catalog visibility:** a course created with `/iblai-api-studio-course-create` is registered in the ibl.ai catalog for its org at creation and appears in the LMS app's catalog immediately; settings written through `/iblai-api-studio-settings` (subject, tags, level, …) show up in `course_metadata` and the catalog without a separate sync. Api-Token catalog operations (programs, pathways, bulk enrollment, metadata for other orgs) are `/iblai-api-catalog` and `/iblai-api-catalog-invitation`.
- "Not visible" checklist: `enroll_status.is_enrolled` → the unit present in `course_outline` (published + released) → `courses/v1/courses` `start` in the past → `hidden`/`invitation_only` false.
- The LMS app's course page is `$LMS_APP_URL/platform/<org>/courses/<course_key>`; courseware is `…/course-content/<course_key>/course` (add `?unit_id=<unit locator>` to deep link).
- The LMS app itself authenticates with a JWT (`Authorization: JWT …`) to the same endpoints; the session cookie is equivalent for these reads and lasts longer.
- `students_update_enrollment` is form-encoded, so the example drops the JSON content type (`"${L[@]:0:11}"` keeps cookies, CSRF, Origin, Referer, Accept).

Attribution

iblaiiblai
View sourceMore from iblai →
SSkills DirectorySkills Directory

Know which skills are safe — weekly.

Best new skills + every skill we flagged as malicious. From the team that scanned 103,619.

Join free

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments (0)

No comments yet. Be the first to comment!

SSkills DirectorySkills Directory

Know which skills are safe — weekly.

Best new skills + every skill we flagged as malicious. From the team that scanned 103,619.

Join free

Related Skills

Browser Extension Developer

Use this skill when developing or maintaining browser extension code in the `browser/` directory, including Chrome/Firefox/Edge compatibility, content scripts, background scripts, or i18n updates.

281612 votes

Seo Optimizer

SEO optimization with keyword analysis, readability assessment, technical validation, content quality. Use for search rankings, blog posts, content audits, or encountering keyword density, readability scores, meta tags, schema markup errors.

2132 votes

Google Official Seo Guide

Official Google SEO guide covering search optimization, best practices, Search Console, crawling, indexing, and improving website search visibility based on official Google documentation

1862 votes

Tanstack Start

Build a full-stack TanStack Start app on Cloudflare Workers from scratch — SSR, file-based routing, server functions, D1+Drizzle, better-auth, Tailwind v4+shadcn/ui. Use whenever the user mentions TanStack Start, asks to scaffold a full-stack Cloudflare app with SSR, wants an SSR dashboard, or asks for a React 19 + Cloudflare Workers app with file-based routing and server functions — even if they don't name TanStack Start specifically. No template repo — Claude generates every file fresh per ...

9881 votes

Pentest

PTES-aligned adversarial security audit for backend, frontend, and mobile applications. Produces a CVSS-scored Hacker Report with verified PoCs and phased remediation.

5491 votes
View all in development →