{
  "schemaVersion": "1.0",
  "item": {
    "slug": "bunpro-sync",
    "name": "Bunpro",
    "source": "tencent",
    "type": "skill",
    "category": "开发工具",
    "sourceUrl": "https://clawhub.ai/mart1n-xyz/bunpro-sync",
    "canonicalUrl": "https://clawhub.ai/mart1n-xyz/bunpro-sync",
    "targetPlatform": "OpenClaw"
  },
  "install": {
    "downloadMode": "redirect",
    "downloadUrl": "/downloads/bunpro-sync",
    "sourceDownloadUrl": "https://wry-manatee-359.convex.site/api/v1/download?slug=bunpro-sync",
    "sourcePlatform": "tencent",
    "targetPlatform": "OpenClaw",
    "installMethod": "Manual import",
    "extraction": "Extract archive",
    "prerequisites": [
      "OpenClaw"
    ],
    "packageFormat": "ZIP package",
    "includedAssets": [
      "SKILL.md",
      "scripts/sync.py",
      "scripts/queries.py",
      "references/api-structure.md"
    ],
    "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. 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. Summarize what changed and any follow-up checks I should run."
        }
      ]
    },
    "sourceHealth": {
      "source": "tencent",
      "status": "healthy",
      "reason": "direct_download_ok",
      "recommendedAction": "download",
      "checkedAt": "2026-04-30T16:55:25.780Z",
      "expiresAt": "2026-05-07T16:55:25.780Z",
      "httpStatus": 200,
      "finalUrl": "https://wry-manatee-359.convex.site/api/v1/download?slug=network",
      "contentType": "application/zip",
      "probeMethod": "head",
      "details": {
        "probeUrl": "https://wry-manatee-359.convex.site/api/v1/download?slug=network",
        "contentDisposition": "attachment; filename=\"network-1.0.0.zip\"",
        "redirectLocation": null,
        "bodySnippet": null
      },
      "scope": "source",
      "summary": "Source download looks usable.",
      "detail": "Yavira can redirect you to the upstream package for this source.",
      "primaryActionLabel": "Download for OpenClaw",
      "primaryActionHref": "/downloads/bunpro-sync"
    },
    "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/bunpro-sync",
    "agentPageUrl": "https://openagent3.xyz/skills/bunpro-sync/agent",
    "manifestUrl": "https://openagent3.xyz/skills/bunpro-sync/agent.json",
    "briefUrl": "https://openagent3.xyz/skills/bunpro-sync/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. 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. Summarize what changed and any follow-up checks I should run."
      }
    ]
  },
  "documentation": {
    "source": "clawhub",
    "primaryDoc": "SKILL.md",
    "sections": [
      {
        "title": "Bunpro Sync",
        "body": "Sync your Bunpro grammar learning progress locally for analysis and insights.\n\n⚠️ Important: This uses a community-documented API. The official Bunpro API Key from settings does NOT work - you need the Frontend API Token from your browser."
      },
      {
        "title": "Overview",
        "body": "This skill fetches your Japanese grammar progress from Bunpro and stores it in a local SQLite database. Track SRS stages, review forecasts, JLPT progress, and identify grammar leeches (items that keep falling back)."
      },
      {
        "title": "API Keys: The Two Different Tokens",
        "body": "Bunpro has two different API tokens that serve different purposes:"
      },
      {
        "title": "❌ DO NOT USE: \"Official\" API Key (from Settings)",
        "body": "Found at: bunpro.jp/settings/account\nLooks like: d406663ff421af27c87caaa62eefdb7a (32 hex characters)\nDoes NOT work with the Frontend API endpoints this skill uses\nReturns 401 Unauthorized errors"
      },
      {
        "title": "✅ USE THIS: Frontend API Token (from Browser)",
        "body": "Found in: Browser DevTools → Console or Application Storage\nLooks like: eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9... (long JWT, 200+ chars)\nThis is what the skill requires\nExpires periodically (you'll need to refresh it)"
      },
      {
        "title": "How to Get the Frontend API Token",
        "body": "Method 1: Console (Recommended)\n\nGo to bunpro.jp and log in\nPress F12 to open DevTools\nClick the Console tab\nPaste this JavaScript and press Enter:\nObject.fromEntries(\n  new URLSearchParams(\n    document.cookie.replace(/; /g, '&')\n  )\n).frontend_api_token\n\n\nCopy the long string that appears (starts with eyJ)\n\nMethod 2: Local Storage\n\nGo to bunpro.jp and log in\nPress F12 → Application tab (or Storage in Firefox)\nIn the left sidebar, expand Local Storage → https://bunpro.jp\nLook for token, authToken, or frontend_api_token\nCopy the value (starts with eyJ)\n\nMethod 3: Network Tab\n\nGo to bunpro.jp and log in\nPress F12 → Network tab\nRefresh the page\nLook for any API call (like /user or /queue)\nClick it → Headers → Request Headers\nFind Authorization: Bearer eyJ...\nCopy the part after \"Bearer \"\n\n⚠️ Token Expiry:\nThe Frontend API Token expires eventually (days/weeks). When you get 401 errors, repeat the steps above to get a fresh token."
      },
      {
        "title": "Sync All Data",
        "body": "# Using environment variable (recommended)\nexport BUNPRO_FRONTEND_API_TOKEN=\"eyJ0eXAiOiJKV1Qi...\"\npython3 scripts/sync.py\n\n# Or pass token directly (less secure)\npython3 scripts/sync.py --token \"eyJ0eXAiOiJKV1Qi...\"\n\n# Store in specific directory\npython3 scripts/sync.py --data-dir ~/bunpro-data"
      },
      {
        "title": "Sync Specific Data",
        "body": "# Only user info\npython3 scripts/sync.py --user-only\n\n# Only study queue\npython3 scripts/sync.py --queue-only\n\n# Only reviews\npython3 scripts/sync.py --reviews-only"
      },
      {
        "title": "Force Full Sync",
        "body": "python3 scripts/sync.py --full"
      },
      {
        "title": "user",
        "body": "Your account info including level, XP, buncoin, lifetime status."
      },
      {
        "title": "grammar_points",
        "body": "Grammar content including title, meaning, structure, JLPT level, unit/lesson."
      },
      {
        "title": "reviews",
        "body": "Your SRS progress on each grammar point (stage, next review, burned status)."
      },
      {
        "title": "study_queue",
        "body": "Items scheduled for future review."
      },
      {
        "title": "due_items",
        "body": "Items currently available for review (includes is_leech flag)."
      },
      {
        "title": "user_stats",
        "body": "Aggregated statistics (SRS overview, forecasts, JLPT progress, activity)."
      },
      {
        "title": "review_histories",
        "body": "Review session history (last session, last 24h)."
      },
      {
        "title": "sync_meta",
        "body": "Internal table tracking last sync timestamps."
      },
      {
        "title": "Common Queries",
        "body": "-- Grammar mastery by JLPT level\nSELECT jlpt_level, COUNT(*) as total,\n       SUM(CASE WHEN burned = 1 THEN 1 ELSE 0 END) as burned\nFROM reviews r\nJOIN grammar_points g ON r.grammar_point_id = g.id\nGROUP BY jlpt_level;\n\n-- Upcoming reviews\nSELECT DATE(next_review) as day, COUNT(*)\nFROM reviews\nWHERE next_review > datetime('now')\nGROUP BY day\nORDER BY day\nLIMIT 7;\n\n-- Grammar leeches\nSELECT g.title, g.meaning, d.streak, r.srs_stage_string\nFROM due_items d\nJOIN grammar_points g ON d.reviewable_id = g.id\nLEFT JOIN reviews r ON d.reviewable_id = r.reviewable_id\nWHERE d.is_leech = 1\nORDER BY d.streak ASC;"
      },
      {
        "title": "Query Tools",
        "body": "# Show SRS distribution\npython3 scripts/queries.py srs\n\n# Show upcoming review forecast\npython3 scripts/queries.py forecast\n\n# Show grammar mastery by JLPT level\npython3 scripts/queries.py grammar --jlpt 5\n\n# Show currently due reviews\npython3 scripts/queries.py due\n\n# Show grammar leeches\npython3 scripts/queries.py leeches\n\n# Show overall progress\npython3 scripts/queries.py progress\n\n# Show recent activity\npython3 scripts/queries.py activity"
      },
      {
        "title": "API Notes",
        "body": "Base URL: https://api.bunpro.jp/api/frontend\nAuth: Bearer JWT token from browser (not settings API key)\nRate limits: Unknown - be reasonable\nStability: Community-documented, may change without notice\nPermission: Reverse-engineered with permission from Bunpro team"
      },
      {
        "title": "Troubleshooting",
        "body": "401 Unauthorized:\n\nToken expired (get fresh one from browser)\nUsing wrong token type (need Frontend API Token, not settings API key)\nToken format should be JWT (eyJ0eXAi...)\n\n500 Server Error:\n\nBunpro API may be down\nEndpoint may have changed\nCheck Bunpro Community API docs\n\nEmpty data:\n\nYou're in vacation mode (check bunpro.jp)\nNo reviews done yet\nDifferent endpoint structure than expected"
      },
      {
        "title": "References",
        "body": "Bunpro Community API GitHub\nBunpro Community Forum API Discussion\nPostman Collection\nreferences/api-structure.md - Full endpoint documentation"
      },
      {
        "title": "Files",
        "body": "scripts/sync.py - Main sync tool with CLI\nscripts/queries.py - Query helper with common reports\nreferences/api-structure.md - Bunpro API reference"
      }
    ],
    "body": "Bunpro Sync\n\nSync your Bunpro grammar learning progress locally for analysis and insights.\n\n⚠️ Important: This uses a community-documented API. The official Bunpro API Key from settings does NOT work - you need the Frontend API Token from your browser.\n\nOverview\n\nThis skill fetches your Japanese grammar progress from Bunpro and stores it in a local SQLite database. Track SRS stages, review forecasts, JLPT progress, and identify grammar leeches (items that keep falling back).\n\nAPI Keys: The Two Different Tokens\n\nBunpro has two different API tokens that serve different purposes:\n\n❌ DO NOT USE: \"Official\" API Key (from Settings)\nFound at: bunpro.jp/settings/account\nLooks like: d406663ff421af27c87caaa62eefdb7a (32 hex characters)\nDoes NOT work with the Frontend API endpoints this skill uses\nReturns 401 Unauthorized errors\n✅ USE THIS: Frontend API Token (from Browser)\nFound in: Browser DevTools → Console or Application Storage\nLooks like: eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9... (long JWT, 200+ chars)\nThis is what the skill requires\nExpires periodically (you'll need to refresh it)\nHow to Get the Frontend API Token\n\nMethod 1: Console (Recommended)\n\nGo to bunpro.jp and log in\nPress F12 to open DevTools\nClick the Console tab\nPaste this JavaScript and press Enter:\nObject.fromEntries(\n  new URLSearchParams(\n    document.cookie.replace(/; /g, '&')\n  )\n).frontend_api_token\n\nCopy the long string that appears (starts with eyJ)\n\nMethod 2: Local Storage\n\nGo to bunpro.jp and log in\nPress F12 → Application tab (or Storage in Firefox)\nIn the left sidebar, expand Local Storage → https://bunpro.jp\nLook for token, authToken, or frontend_api_token\nCopy the value (starts with eyJ)\n\nMethod 3: Network Tab\n\nGo to bunpro.jp and log in\nPress F12 → Network tab\nRefresh the page\nLook for any API call (like /user or /queue)\nClick it → Headers → Request Headers\nFind Authorization: Bearer eyJ...\nCopy the part after \"Bearer \"\n\n⚠️ Token Expiry: The Frontend API Token expires eventually (days/weeks). When you get 401 errors, repeat the steps above to get a fresh token.\n\nQuick Start\nSync All Data\n# Using environment variable (recommended)\nexport BUNPRO_FRONTEND_API_TOKEN=\"eyJ0eXAiOiJKV1Qi...\"\npython3 scripts/sync.py\n\n# Or pass token directly (less secure)\npython3 scripts/sync.py --token \"eyJ0eXAiOiJKV1Qi...\"\n\n# Store in specific directory\npython3 scripts/sync.py --data-dir ~/bunpro-data\n\nSync Specific Data\n# Only user info\npython3 scripts/sync.py --user-only\n\n# Only study queue\npython3 scripts/sync.py --queue-only\n\n# Only reviews\npython3 scripts/sync.py --reviews-only\n\nForce Full Sync\npython3 scripts/sync.py --full\n\nDatabase Schema\nuser\n\nYour account info including level, XP, buncoin, lifetime status.\n\ngrammar_points\n\nGrammar content including title, meaning, structure, JLPT level, unit/lesson.\n\nreviews\n\nYour SRS progress on each grammar point (stage, next review, burned status).\n\nstudy_queue\n\nItems scheduled for future review.\n\ndue_items\n\nItems currently available for review (includes is_leech flag).\n\nuser_stats\n\nAggregated statistics (SRS overview, forecasts, JLPT progress, activity).\n\nreview_histories\n\nReview session history (last session, last 24h).\n\nsync_meta\n\nInternal table tracking last sync timestamps.\n\nCommon Queries\n-- Grammar mastery by JLPT level\nSELECT jlpt_level, COUNT(*) as total,\n       SUM(CASE WHEN burned = 1 THEN 1 ELSE 0 END) as burned\nFROM reviews r\nJOIN grammar_points g ON r.grammar_point_id = g.id\nGROUP BY jlpt_level;\n\n-- Upcoming reviews\nSELECT DATE(next_review) as day, COUNT(*)\nFROM reviews\nWHERE next_review > datetime('now')\nGROUP BY day\nORDER BY day\nLIMIT 7;\n\n-- Grammar leeches\nSELECT g.title, g.meaning, d.streak, r.srs_stage_string\nFROM due_items d\nJOIN grammar_points g ON d.reviewable_id = g.id\nLEFT JOIN reviews r ON d.reviewable_id = r.reviewable_id\nWHERE d.is_leech = 1\nORDER BY d.streak ASC;\n\nQuery Tools\n# Show SRS distribution\npython3 scripts/queries.py srs\n\n# Show upcoming review forecast\npython3 scripts/queries.py forecast\n\n# Show grammar mastery by JLPT level\npython3 scripts/queries.py grammar --jlpt 5\n\n# Show currently due reviews\npython3 scripts/queries.py due\n\n# Show grammar leeches\npython3 scripts/queries.py leeches\n\n# Show overall progress\npython3 scripts/queries.py progress\n\n# Show recent activity\npython3 scripts/queries.py activity\n\nAPI Notes\nBase URL: https://api.bunpro.jp/api/frontend\nAuth: Bearer JWT token from browser (not settings API key)\nRate limits: Unknown - be reasonable\nStability: Community-documented, may change without notice\nPermission: Reverse-engineered with permission from Bunpro team\nTroubleshooting\n\n401 Unauthorized:\n\nToken expired (get fresh one from browser)\nUsing wrong token type (need Frontend API Token, not settings API key)\nToken format should be JWT (eyJ0eXAi...)\n\n500 Server Error:\n\nBunpro API may be down\nEndpoint may have changed\nCheck Bunpro Community API docs\n\nEmpty data:\n\nYou're in vacation mode (check bunpro.jp)\nNo reviews done yet\nDifferent endpoint structure than expected\nReferences\nBunpro Community API GitHub\nBunpro Community Forum API Discussion\nPostman Collection\nreferences/api-structure.md - Full endpoint documentation\nFiles\nscripts/sync.py - Main sync tool with CLI\nscripts/queries.py - Query helper with common reports\nreferences/api-structure.md - Bunpro API reference"
  },
  "trust": {
    "sourceLabel": "tencent",
    "provenanceUrl": "https://clawhub.ai/mart1n-xyz/bunpro-sync",
    "publisherUrl": "https://clawhub.ai/mart1n-xyz/bunpro-sync",
    "owner": "mart1n-xyz",
    "version": "1.0.0",
    "license": null,
    "verificationStatus": "Indexed source record"
  },
  "links": {
    "detailUrl": "https://openagent3.xyz/skills/bunpro-sync",
    "downloadUrl": "https://openagent3.xyz/downloads/bunpro-sync",
    "agentUrl": "https://openagent3.xyz/skills/bunpro-sync/agent",
    "manifestUrl": "https://openagent3.xyz/skills/bunpro-sync/agent.json",
    "briefUrl": "https://openagent3.xyz/skills/bunpro-sync/agent.md"
  }
}