{
  "schemaVersion": "1.0",
  "item": {
    "slug": "edstem",
    "name": "EdStem",
    "source": "tencent",
    "type": "skill",
    "category": "通讯协作",
    "sourceUrl": "https://clawhub.ai/axel5o5/edstem",
    "canonicalUrl": "https://clawhub.ai/axel5o5/edstem",
    "targetPlatform": "OpenClaw"
  },
  "install": {
    "downloadMode": "redirect",
    "downloadUrl": "/downloads/edstem",
    "sourceDownloadUrl": "https://wry-manatee-359.convex.site/api/v1/download?slug=edstem",
    "sourcePlatform": "tencent",
    "targetPlatform": "OpenClaw",
    "installMethod": "Manual import",
    "extraction": "Extract archive",
    "prerequisites": [
      "OpenClaw"
    ],
    "packageFormat": "ZIP package",
    "includedAssets": [
      "CHANGELOG.md",
      "MIGRATION_NOTES.md",
      "PUBLISHING.md",
      "README.md",
      "SKILL.md",
      "scripts/fetch-edstem.py"
    ],
    "primaryDoc": "SKILL.md",
    "quickSetup": [
      "Download the package from Yavira.",
      "Extract the archive and review SKILL.md first.",
      "Import or place the package into your OpenClaw setup."
    ],
    "agentAssist": {
      "summary": "Hand the extracted package to your coding agent with a concrete install brief instead of figuring it out manually.",
      "steps": [
        "Download the package from Yavira.",
        "Extract it into a folder your agent can access.",
        "Paste one of the prompts below and point your agent at the extracted folder."
      ],
      "prompts": [
        {
          "label": "New install",
          "body": "I downloaded a skill package from Yavira. Read SKILL.md from the extracted folder and install it by following the included instructions. Then review README.md for any prerequisites, environment setup, or post-install checks. Tell me what you changed and call out any manual steps you could not complete."
        },
        {
          "label": "Upgrade existing",
          "body": "I downloaded an updated skill package from Yavira. Read SKILL.md from the extracted folder, compare it with my current installation, and upgrade it while preserving any custom configuration unless the package docs explicitly say otherwise. Then review README.md for any prerequisites, environment setup, or post-install checks. Summarize what changed and any follow-up checks I should run."
        }
      ]
    },
    "sourceHealth": {
      "source": "tencent",
      "slug": "edstem",
      "status": "healthy",
      "reason": "direct_download_ok",
      "recommendedAction": "download",
      "checkedAt": "2026-04-30T00:27:15.319Z",
      "expiresAt": "2026-05-07T00:27:15.319Z",
      "httpStatus": 200,
      "finalUrl": "https://wry-manatee-359.convex.site/api/v1/download?slug=edstem",
      "contentType": "application/zip",
      "probeMethod": "head",
      "details": {
        "probeUrl": "https://wry-manatee-359.convex.site/api/v1/download?slug=edstem",
        "contentDisposition": "attachment; filename=\"edstem-1.1.0.zip\"",
        "redirectLocation": null,
        "bodySnippet": null,
        "slug": "edstem"
      },
      "scope": "item",
      "summary": "Item download looks usable.",
      "detail": "Yavira can redirect you to the upstream package for this item.",
      "primaryActionLabel": "Download for OpenClaw",
      "primaryActionHref": "/downloads/edstem"
    },
    "validation": {
      "installChecklist": [
        "Use the Yavira download entry.",
        "Review SKILL.md after the package is downloaded.",
        "Confirm the extracted package contains the expected setup assets."
      ],
      "postInstallChecks": [
        "Confirm the extracted package includes the expected docs or setup files.",
        "Validate the skill or prompts are available in your target agent workspace.",
        "Capture any manual follow-up steps the agent could not complete."
      ]
    },
    "downloadPageUrl": "https://openagent3.xyz/downloads/edstem",
    "agentPageUrl": "https://openagent3.xyz/skills/edstem/agent",
    "manifestUrl": "https://openagent3.xyz/skills/edstem/agent.json",
    "briefUrl": "https://openagent3.xyz/skills/edstem/agent.md"
  },
  "agentAssist": {
    "summary": "Hand the extracted package to your coding agent with a concrete install brief instead of figuring it out manually.",
    "steps": [
      "Download the package from Yavira.",
      "Extract it into a folder your agent can access.",
      "Paste one of the prompts below and point your agent at the extracted folder."
    ],
    "prompts": [
      {
        "label": "New install",
        "body": "I downloaded a skill package from Yavira. Read SKILL.md from the extracted folder and install it by following the included instructions. Then review README.md for any prerequisites, environment setup, or post-install checks. Tell me what you changed and call out any manual steps you could not complete."
      },
      {
        "label": "Upgrade existing",
        "body": "I downloaded an updated skill package from Yavira. Read SKILL.md from the extracted folder, compare it with my current installation, and upgrade it while preserving any custom configuration unless the package docs explicitly say otherwise. Then review README.md for any prerequisites, environment setup, or post-install checks. Summarize what changed and any follow-up checks I should run."
      }
    ]
  },
  "documentation": {
    "source": "clawhub",
    "primaryDoc": "SKILL.md",
    "sections": [
      {
        "title": "EdStem",
        "body": "Fetch and organize EdStem discussion threads from any course or institution with automatic staff/student differentiation."
      },
      {
        "title": "Quick Start",
        "body": "Fetch recent threads for any course:\n\ncd /home/axel/.openclaw/workspace/skills/edstem/scripts\npython3 fetch-edstem.py <course_id> [output_dir] [--course-name \"Course Name\"]\n\nExamples:\n\n# Fetch to default directory (./edstem-<course_id>)\npython3 fetch-edstem.py 92041\n\n# Fetch to specific directory\npython3 fetch-edstem.py 92041 ./machine-learning\n\n# Specify course name for clearer output\npython3 fetch-edstem.py 92041 --course-name \"Machine Learning\"\n\n# Combine directory and course name\npython3 fetch-edstem.py 92041 ./ml-course --course-name \"Machine Learning\"\n\n# Fetch more threads (default is 10)\npython3 fetch-edstem.py 92041 --limit 25"
      },
      {
        "title": "Finding Your Course ID",
        "body": "To find your EdStem course ID:\n\nLog into EdStem and navigate to your course\nLook at the URL: https://edstem.org/us/courses/<course_id>/\nThe number in the URL is your course ID\n\nAlternatively, use the API to list your courses:\n\ncurl -H \"Authorization: Bearer YOUR_TOKEN\" https://us.edstem.org/api/user | jq '.courses[] | {id: .course.id, name: .course.name}'"
      },
      {
        "title": "What Gets Fetched",
        "body": "For each course:\n\nthreads.json - Full thread list with metadata\nthread-XXX.md - Individual threads formatted as markdown\n\nThread title, category, timestamps\nOriginal post content\nAll answers and comments\n[STAFF] or [STUDENT] tags on every post"
      },
      {
        "title": "Features",
        "body": "Institution-agnostic: Works with any school using EdStem\nStaff differentiation: Clearly marks instructor/TA posts vs student posts\nStructured output: Markdown format for easy reading and searching\nAPI-based: Uses EdStem's official API (no scraping)\nFlexible output: Choose your own output directory and organization scheme"
      },
      {
        "title": "Authentication",
        "body": "The skill uses a bearer token stored in the Python script. To use with your own account:\n\nLog into EdStem in your browser\nOpen Developer Tools → Network tab\nReload any EdStem page\nFind an API request and copy the Authorization: Bearer ... token\nUpdate ED_TOKEN in scripts/fetch-edstem.py\n\nCurrent token location: Line 20 in scripts/fetch-edstem.py\n\nIf API calls fail (401 Unauthorized), your token likely expired and needs refresh."
      },
      {
        "title": "fetch-edstem.py (recommended)",
        "body": "Full-featured Python script with markdown formatting and staff/student differentiation.\n\nUsage:\n\npython3 scripts/fetch-edstem.py <course_id> [output_dir] [options]\n\nOptions:\n\noutput_dir - Where to save threads (default: ./edstem-<course_id>)\n--course-name NAME - Display name for the course\n--limit N - Number of threads to fetch (default: 10)\n\nFeatures:\n\nFetches thread metadata and full details\nFull markdown formatting with answers and comments\nAutomatic staff role detection\nJSON cache of thread list\nAuto-creates output directory"
      },
      {
        "title": "fetch-edstem.sh (lightweight alternative)",
        "body": "Bash/curl version for raw JSON fetching without dependencies.\n\nUsage:\n\nbash scripts/fetch-edstem.sh <course_id> [output_dir]\n\nOutputs:\n\nRaw JSON files for each thread\nRequires manual formatting or post-processing"
      },
      {
        "title": "Check for new posts",
        "body": "python3 scripts/fetch-edstem.py 92041 ~/courses/ml-spring-2025"
      },
      {
        "title": "Sync multiple courses",
        "body": "# Create a simple sync script\nfor course in \"92041:machine-learning\" \"94832:advanced-rl\"; do\n    IFS=':' read -r id name <<< \"$course\"\n    python3 scripts/fetch-edstem.py $id ~/courses/$name --course-name \"$name\"\ndone"
      },
      {
        "title": "Review recent activity",
        "body": "After fetching, check the markdown files:\n\nls -lt ./edstem-92041/*.md | head\ncat ./edstem-92041/thread-001.md"
      },
      {
        "title": "Search across threads",
        "body": "grep -r \"gradient descent\" ./edstem-92041/*.md"
      },
      {
        "title": "Output Structure",
        "body": "<output_dir>/\n├── threads.json              # Thread metadata\n├── thread-001.md             # Individual threads\n├── thread-002.md\n└── ...\n\nEach markdown file contains:\n\nThread metadata (number, title, category, timestamps)\nOriginal post with author role\nAll answers (sorted, with role tags)\nAll comments (with role tags)"
      },
      {
        "title": "With LLM agents",
        "body": "# Fetch threads and analyze with your agent\npython3 fetch-edstem.py 92041 ./course-data\n# Then: \"Summarize the most common questions in ./course-data/\""
      },
      {
        "title": "Automated monitoring",
        "body": "# Add to cron for daily sync\n0 9 * * * cd /path/to/skills/edstem/scripts && python3 fetch-edstem.py 92041 ~/courses/ml"
      },
      {
        "title": "Custom organization",
        "body": "# Organize by semester and institution\npython3 fetch-edstem.py 92041 ~/school/stanford/2025-spring/cs229\npython3 fetch-edstem.py 94832 ~/school/mit/2025-spring/6.7920"
      },
      {
        "title": "Troubleshooting",
        "body": "401 Unauthorized: Token expired. Re-authenticate and update ED_TOKEN in the script.\n\nCourse not found: Verify the course ID and that your account has access.\n\nEmpty threads: Check that the course has discussion posts and you're enrolled.\n\nRate limiting: EdStem may rate-limit API requests. Add delays between fetches if needed."
      },
      {
        "title": "Contributing",
        "body": "This skill is open-source and institution-agnostic by design. Improvements welcome:\n\nBetter content parsing (EdStem uses XML-based document format)\nSupport for filtering by category or date range\nIncremental sync (only fetch new threads)\nExport to other formats (JSON, HTML, etc.)"
      },
      {
        "title": "Version History",
        "body": "1.1.0 - Made institution-agnostic with flexible parameters\n1.0.0 - Initial release"
      }
    ],
    "body": "EdStem\n\nFetch and organize EdStem discussion threads from any course or institution with automatic staff/student differentiation.\n\nQuick Start\n\nFetch recent threads for any course:\n\ncd /home/axel/.openclaw/workspace/skills/edstem/scripts\npython3 fetch-edstem.py <course_id> [output_dir] [--course-name \"Course Name\"]\n\n\nExamples:\n\n# Fetch to default directory (./edstem-<course_id>)\npython3 fetch-edstem.py 92041\n\n# Fetch to specific directory\npython3 fetch-edstem.py 92041 ./machine-learning\n\n# Specify course name for clearer output\npython3 fetch-edstem.py 92041 --course-name \"Machine Learning\"\n\n# Combine directory and course name\npython3 fetch-edstem.py 92041 ./ml-course --course-name \"Machine Learning\"\n\n# Fetch more threads (default is 10)\npython3 fetch-edstem.py 92041 --limit 25\n\nFinding Your Course ID\n\nTo find your EdStem course ID:\n\nLog into EdStem and navigate to your course\nLook at the URL: https://edstem.org/us/courses/<course_id>/\nThe number in the URL is your course ID\n\nAlternatively, use the API to list your courses:\n\ncurl -H \"Authorization: Bearer YOUR_TOKEN\" https://us.edstem.org/api/user | jq '.courses[] | {id: .course.id, name: .course.name}'\n\nWhat Gets Fetched\n\nFor each course:\n\nthreads.json - Full thread list with metadata\nthread-XXX.md - Individual threads formatted as markdown\nThread title, category, timestamps\nOriginal post content\nAll answers and comments\n[STAFF] or [STUDENT] tags on every post\nFeatures\nInstitution-agnostic: Works with any school using EdStem\nStaff differentiation: Clearly marks instructor/TA posts vs student posts\nStructured output: Markdown format for easy reading and searching\nAPI-based: Uses EdStem's official API (no scraping)\nFlexible output: Choose your own output directory and organization scheme\nAuthentication\n\nThe skill uses a bearer token stored in the Python script. To use with your own account:\n\nLog into EdStem in your browser\nOpen Developer Tools → Network tab\nReload any EdStem page\nFind an API request and copy the Authorization: Bearer ... token\nUpdate ED_TOKEN in scripts/fetch-edstem.py\n\nCurrent token location: Line 20 in scripts/fetch-edstem.py\n\nIf API calls fail (401 Unauthorized), your token likely expired and needs refresh.\n\nScripts\nfetch-edstem.py (recommended)\n\nFull-featured Python script with markdown formatting and staff/student differentiation.\n\nUsage:\n\npython3 scripts/fetch-edstem.py <course_id> [output_dir] [options]\n\n\nOptions:\n\noutput_dir - Where to save threads (default: ./edstem-<course_id>)\n--course-name NAME - Display name for the course\n--limit N - Number of threads to fetch (default: 10)\n\nFeatures:\n\nFetches thread metadata and full details\nFull markdown formatting with answers and comments\nAutomatic staff role detection\nJSON cache of thread list\nAuto-creates output directory\nfetch-edstem.sh (lightweight alternative)\n\nBash/curl version for raw JSON fetching without dependencies.\n\nUsage:\n\nbash scripts/fetch-edstem.sh <course_id> [output_dir]\n\n\nOutputs:\n\nRaw JSON files for each thread\nRequires manual formatting or post-processing\nCommon Workflows\nCheck for new posts\npython3 scripts/fetch-edstem.py 92041 ~/courses/ml-spring-2025\n\nSync multiple courses\n# Create a simple sync script\nfor course in \"92041:machine-learning\" \"94832:advanced-rl\"; do\n    IFS=':' read -r id name <<< \"$course\"\n    python3 scripts/fetch-edstem.py $id ~/courses/$name --course-name \"$name\"\ndone\n\nReview recent activity\n\nAfter fetching, check the markdown files:\n\nls -lt ./edstem-92041/*.md | head\ncat ./edstem-92041/thread-001.md\n\nSearch across threads\ngrep -r \"gradient descent\" ./edstem-92041/*.md\n\nOutput Structure\n<output_dir>/\n├── threads.json              # Thread metadata\n├── thread-001.md             # Individual threads\n├── thread-002.md\n└── ...\n\n\nEach markdown file contains:\n\nThread metadata (number, title, category, timestamps)\nOriginal post with author role\nAll answers (sorted, with role tags)\nAll comments (with role tags)\nIntegration Examples\nWith LLM agents\n# Fetch threads and analyze with your agent\npython3 fetch-edstem.py 92041 ./course-data\n# Then: \"Summarize the most common questions in ./course-data/\"\n\nAutomated monitoring\n# Add to cron for daily sync\n0 9 * * * cd /path/to/skills/edstem/scripts && python3 fetch-edstem.py 92041 ~/courses/ml\n\nCustom organization\n# Organize by semester and institution\npython3 fetch-edstem.py 92041 ~/school/stanford/2025-spring/cs229\npython3 fetch-edstem.py 94832 ~/school/mit/2025-spring/6.7920\n\nTroubleshooting\n\n401 Unauthorized: Token expired. Re-authenticate and update ED_TOKEN in the script.\n\nCourse not found: Verify the course ID and that your account has access.\n\nEmpty threads: Check that the course has discussion posts and you're enrolled.\n\nRate limiting: EdStem may rate-limit API requests. Add delays between fetches if needed.\n\nContributing\n\nThis skill is open-source and institution-agnostic by design. Improvements welcome:\n\nBetter content parsing (EdStem uses XML-based document format)\nSupport for filtering by category or date range\nIncremental sync (only fetch new threads)\nExport to other formats (JSON, HTML, etc.)\nVersion History\n1.1.0 - Made institution-agnostic with flexible parameters\n1.0.0 - Initial release"
  },
  "trust": {
    "sourceLabel": "tencent",
    "provenanceUrl": "https://clawhub.ai/axel5o5/edstem",
    "publisherUrl": "https://clawhub.ai/axel5o5/edstem",
    "owner": "axel5o5",
    "version": "1.1.0",
    "license": null,
    "verificationStatus": "Indexed source record"
  },
  "links": {
    "detailUrl": "https://openagent3.xyz/skills/edstem",
    "downloadUrl": "https://openagent3.xyz/downloads/edstem",
    "agentUrl": "https://openagent3.xyz/skills/edstem/agent",
    "manifestUrl": "https://openagent3.xyz/skills/edstem/agent.json",
    "briefUrl": "https://openagent3.xyz/skills/edstem/agent.md"
  }
}