Skill: agents365-ai/figshare-skill (version 0.1.0)

--- name: figshare-skill description: Use whenever the user wants to interact with Figshare - searching public datasets/articles, downloading Figshare files, listing their own articles/collections/projects, creating or updating articles, or uploading files (including large multi-part uploads) via the Figshare v2 REST API. Trigger on mentions of "figshare", figshare DOIs (10.6084/m9.figshare.*), figshare.com URLs, or phrases like "upload my dataset to figshare", "publish to figshare", "get figshare article". homepage: https://github.com/Agents365-ai/figshare-skill license: MIT --- # Figshare Skill Interact with the [Figshare v2 REST API](https://docs.figshare.com/) to search, download, create, and upload research outputs. ## Prerequisites - `curl` and `jq` available on PATH. - For authenticated endpoints (anything under `/account/...` or uploads), a **personal token** from https://figshare.com/account/applications exported as: ```bash export FIGSHARE_TOKEN=xxxxxxxxxxxxxxxx ``` - Public endpoints (search, public articles, downloads) need no token. Always confirm with the user before creating, modifying, publishing, or deleting anything on their account — these are hard to reverse. ## API Basics - **Base URL:** `https://api.figshare.com/v2` - **Auth header:** `Authorization: token $FIGSHARE_TOKEN` - **Content-Type:** `application/json` for POST/PUT bodies - **Rate limit:** keep it under ~1 request/second to avoid abuse throttling - **Errors:** JSON body with `message`, `code`; common codes 400/401/403/404/422 ## Common Recipes ### Search public articles ```bash curl -s -X POST https://api.figshare.com/v2/articles/search \ -H "Content-Type: application/json" \ -d '{"search_for": ":title: single cell", "page_size": 20}' | jq ``` Field operators: `:title:`, `:author:`, `:tag:`, `:category:`, `:doi:`, `:resource_doi:`. ### Get a public article (by ID or DOI) ```bash curl -s https://api.figshare.com/v2/articles/{article_id} | jq # or resolve from a figshare.com URL: the numeric tail is the article_id ``` ### Download all files from a public article ```bash ART=12345678 curl -s https://api.figshare.com/v2/articles/$ART/files \ | jq -r '.[] | "\(.download_url)\t\(.name)"' \ | while IFS=$'\t' read -r url name; do curl -L -o "$name" "$url"; done ``` ### List your own articles ```bash curl -s -H "Authorization: token $FIGSHARE_TOKEN" \ "https://api.figshare.com/v2/account/articles?page=1&page_size=50" | jq ``` ### Create an article (draft) ```bash curl -s -X POST https://api.figshare.com/v2/account/articles \ -H "Authorization: token $FIGSHARE_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "title": "My dataset", "description": "Full description here.", "defined_type": "dataset", "tags": ["demo"], "categories": [2] }' | jq ``` Response is `{ "location": ".../account/articles/{id}", "entity_id": 123 }`. ### Update / publish an article ```bash # update metadata curl -s -X PUT https://api.figshare.com/v2/account/articles/$ART \ -H "Authorization: token $FIGSHARE_TOKEN" \ -H "Content-Type: application/json" \ -d '{"title": "New title"}' # publish (becomes public, assigns DOI, version is frozen) curl -s -X POST https://api.figshare.com/v2/account/articles/$ART/publish \ -H "Authorization: token $FIGSHARE_TOKEN" ``` Always ask before publishing — it's permanent for that version. ### Collections & projects ```bash # create collection that groups existing articles curl -s -X POST https://api.figshare.com/v2/account/collections \ -H "Authorization: token $FIGSHARE_TOKEN" \ -H "Content-Type: application/json" \ -d '{"title": "My Collection", "articles": [123, 456]}' # create project curl -s -X POST https://api.figshare.com/v2/account/projects \ -H "Authorization: token $FIGSHARE_TOKEN" \ -H "Content-Type: application/json" \ -d '{"title": "Research Project"}' ``` ## Uploading Files (Multi-part Flow) Figshare uploads are **3-step**: initiate → PUT each part → complete. Use the bundled helpers for anything non-trivial: ```bash # upload a file to an existing draft article ./scripts/upload.sh <article_id> <path/to/file> # batch-download every file from a public article (accepts id or figshare.com URL) ./scripts/download.sh <article_id_or_url> [output_dir] # reserve + upload + publish a new version of an already-published article ./scripts/new-version.sh <article_id> <path/to/file> ``` The raw flow, in case you need to adapt it: 1. **Initiate** — compute md5 + size, POST to article: ```bash SIZE=$(stat -f%z "$FILE" 2>/dev/null || stat -c%s "$FILE") MD5=$(md5sum "$FILE" | awk '{print $1}') # or: md5 -q on macOS curl -s -X POST https://api.figshare.com/v2/account/articles/$ART/files \ -H "Authorization: token $FIGSHARE_TOKEN" \ -H "Content-Type: application/json" \ -d "{\"md5\":\"$MD5\",\"name\":\"$(basename $FILE)\",\"size\":$SIZE}" ``` Response has `location` pointing at `/account/articles/$ART/files/$FILE_ID`. 2. **Fetch upload info** from that file record — it contains an `upload_url`. GET the upload_url to learn the part layout (`parts: [{partNo, startOffset, endOffset}]`). 3. **Upload parts** — for each part, PUT the byte range to `${upload_url}/${partNo}`: ```bash dd if="$FILE" bs=1 skip=$START count=$((END-START+1)) 2>/dev/null \ | curl -s -X PUT --data-binary @- "${upload_url}/${partNo}" \ -H "Authorization: token $FIGSHARE_TOKEN" ``` 4. **Complete** — POST to the file record to finalize: ```bash curl -s -X POST https://api.figshare.com/v2/account/articles/$ART/files/$FILE_ID \ -H "Authorization: token $FIGSHARE_TOKEN" ``` Why three steps: Figshare streams large files through a separate upload service. Skipping the complete call leaves the file in a pending state and it won't appear on the article. ## Pagination Most list endpoints accept either `page`+`page_size` or `limit`+`offset`. Max `page_size` is typically 1000. For large harvests, loop until an empty page: ```bash page=1 while :; do out=$(curl -s "https://api.figshare.com/v2/articles?page=$page&page_size=100") [ "$(echo "$out" | jq 'length')" = "0" ] && break echo "$out" | jq -c '.[]' page=$((page+1)) sleep 1 done ``` ## Troubleshooting - **401** — token missing/expired; re-check `$FIGSHARE_TOKEN`. - **403** on `/account/...` — token lacks the needed scope; regenerate with full permissions. - **422** on article create — missing required field (usually `title`) or bad `categories`/`defined_type`. - **Upload parts mismatch** — md5 or size in step 1 didn't match the bytes actually uploaded; recompute and restart. - **Published article won't update** — publishing freezes a version; create a new version instead. ## References - API reference: https://docs.figshare.com/ - Token management: https://figshare.com/account/applications - Category IDs: `GET https://api.figshare.com/v2/categories` - License IDs: `GET https://api.figshare.com/v2/licenses`

path: README.md
content: # figshare-skill — Figshare v2 API from the Command Line

[中文文档](README_CN.md) | [Figshare API Docs](https://docs.figshare.com/)

## What it does

- **Search** public Figshare articles with field operators (`:title:`, `:author:`, `:tag:`, `:category:`, `:doi:`)
- **Batch-download** every file of a public article from an ID, DOI, or `figshare.com` URL
- **List / create / update / publish** your own articles, including draft and version workflows
- **Multi-part upload** for large files — wraps the 3-step `initiate → PUT parts → complete` flow with md5 + part sizing handled automatically
- **New-version publishing** for already-published articles (published versions are frozen)
- **Collections and Projects** management
- Triggers automatically whenever the user mentions Figshare, a `figshare.com` URL, or a `10.6084/m9.figshare.*` DOI

## Multi-Platform Support

Works with all major AI coding agents that support the [Agent Skills](https://agentskills.io) format:

| Platform | Status | Details |
|----------|--------|---------|
| **Claude Code** | ✅ Full support | Native SKILL.md format |
| **OpenClaw** | ✅ Full support | `metadata.openclaw` namespace |
| **SkillsMP** | ✅ Indexed | GitHub topics configured |

## Comparison

### vs No Skill (native agent)

| Feature | Native agent | This skill |
|---------|-------------|------------|
| Knows the Figshare base URL & auth header | Maybe | ✅ |
| Search field operators (`:title:`, `:author:`...) | ❌ | ✅ |
| Public batch download from ID / DOI / URL | ❌ | ✅ helper script |
| Multi-part upload (`initiate → parts → complete`) | ⚠️ reinvents per run | ✅ `upload.sh` |
| md5 / size / part layout handled | ❌ | ✅ automatic |
| New-version publishing | ❌ | ✅ `new-version.sh` |
| Safe-by-default publish / delete | ❌ | ✅ asks first |
| Concrete `curl` + `jq` recipes | ❌ | ✅ inlined |

## Prerequisites

- `curl`
- `jq`
- A [Figshare Personal Token](https://figshare.com/account/applications) for anything that touches `/account/...` or uploads:

  ```bash
  export FIGSHARE_TOKEN=xxxxxxxxxxxxxxxx
  ```

Public search / article / download endpoints work with no token at all.

## Skill Installation

### Claude Code

```bash
# Global install (available in all projects)
git clone https://github.com/Agents365-ai/figshare-skill.git ~/.claude/skills/figshare-skill

# Project-level install
git clone https://github.com/Agents365-ai/figshare-skill.git .claude/skills/figshare-skill
```

### OpenClaw

```bash
git clone https://github.com/Agents365-ai/figshare-skill.git ~/.openclaw/skills/figshare-skill

# Project-level
git clone https://github.com/Agents365-ai/figshare-skill.git skills/figshare-skill
```

### SkillsMP

Browse on [SkillsMP](https://skillsmp.com) or:

```bash
skills install figshare-skill
```

### Installation paths summary

| Platform | Global path | Project path |
|----------|-------------|--------------|
| Claude Code | `~/.claude/skills/figshare-skill/` | `.claude/skills/figshare-skill/` |
| OpenClaw | `~/.openclaw/skills/figshare-skill/` | `skills/figshare-skill/` |
| SkillsMP | N/A (installed via CLI) | N/A |

## Usage

Just describe what you want:

```
> Search figshare for "single cell" datasets and show me the top 10

> Download every file of https://figshare.com/articles/dataset/xxx/31957606 into ./data

> Upload ./results.zip to my draft figshare article 31957803

> Publish a new version of figshare article 12345678 with ./v2.csv
```

The skill picks the right endpoint, fills in authentication, and uses the bundled helper scripts for multi-part uploads.

## Helper Scripts

| Script | Purpose |
|--------|---------|
| `scripts/upload.sh <article_id> <file>` | 3-step multi-part upload to a draft article |
| `scripts/download.sh <id_or_url> [dir]` | Batch-download every file from a public article |
| `scripts/new-version.sh <article_id> <file>` | Reserve, upload, and publish a new version |

All scripts read `FIGSHARE_TOKEN` from the environment and depend only on `curl` + `jq`.

## Files

- `SKILL.md` — **the only required file**. Loaded by all platforms as the skill instructions.
- `scripts/upload.sh` — multi-part upload helper
- `scripts/download.sh` — batch downloader
- `scripts/new-version.sh` — new-version workflow
- `README.md` — this file (English, displayed on GitHub homepage)
- `README_CN.md` — Chinese documentation

## Known Limitations

- **`dd bs=1` is slow for huge parts**: good enough for datasets up to a few GB per part. Very large single files would benefit from a `bs=1M` + `skip=`/`count=` rewrite
- **Rate limiting**: Figshare does not publish a hard limit but recommends ≤1 req/sec. The helpers do not throttle
- **Published versions are immutable**: edits require `new-version.sh`, not `update`
- **Categories / licenses are numeric IDs**: use `GET /v2/categories` and `GET /v2/licenses` to look up the ID you need before creating an article

## License

MIT

## Support

If this skill helps you, consider supporting the author:

<table>
  <tr>
    <td align="center">
      <img src="https://raw.githubusercontent.com/Agents365-ai/images_payment/main/qrcode/wechat-pay.png" width="180" alt="WeChat Pay">
      <br>
      <b>WeChat Pay</b>
    </td>
    <td align="center">
      <img src="https://raw.githubusercontent.com/Agents365-ai/images_payment/main/qrcode/alipay.png" width="180" alt="Alipay">
      <br>
      <b>Alipay</b>
    </td>
    <td align="center">
      <img src="https://raw.githubusercontent.com/Agents365-ai/images_payment/main/qrcode/buymeacoffee.png" width="180" alt="Buy Me a Coffee">
      <br>
      <b>Buy Me a Coffee</b>
    </td>
  </tr>
</table>

## Author

**Agents365-ai**

- Bilibili: https://space.bilibili.com/441831884
- GitHub: https://github.com/Agents365-ai


path: README_CN.md
content: # figshare-skill — 命令行下的 Figshare v2 API

[English](README.md) | [Figshare API 文档](https://docs.figshare.com/)

## 功能特性

- **搜索** Figshare 公开文章，支持字段操作符（`:title:`、`:author:`、`:tag:`、`:category:`、`:doi:`）
- **批量下载** 一篇公开文章的全部文件，支持 ID / DOI / `figshare.com` URL
- **列表 / 创建 / 更新 / 发布** 自己的文章，覆盖草稿与版本发布流程
- **多分片上传**，封装 `initiate → PUT parts → complete` 三步流程，自动处理 md5 与分片大小
- **新版本发布** —— 已发布版本不可修改，新版本通过脚本一步完成
- **Collections / Projects** 管理
- 当用户提到 Figshare、`figshare.com` 链接或 `10.6084/m9.figshare.*` DOI 时自动触发

## 多平台支持

适配所有支持 [Agent Skills](https://agentskills.io) 格式的 AI 编程助手：

| 平台 | 状态 | 说明 |
|------|------|------|
| **Claude Code** | ✅ 完全支持 | 原生 SKILL.md 格式 |
| **OpenClaw** | ✅ 完全支持 | `metadata.openclaw` 命名空间 |
| **SkillsMP** | ✅ 已收录 | GitHub topics 已配置 |

## 对比

### vs 原生 Agent（无技能）

| 能力 | 原生 Agent | 本技能 |
|------|-----------|--------|
| 知道 Figshare 基础 URL 与认证头 | 或许 | ✅ |
| 搜索字段操作符（`:title:`、`:author:` 等） | ❌ | ✅ |
| 从 ID / DOI / URL 批量下载公开文章 | ❌ | ✅ 脚本 |
| 多分片上传（`initiate → parts → complete`） | ⚠️ 每次重写 | ✅ `upload.sh` |
| 自动处理 md5 / 大小 / 分片布局 | ❌ | ✅ |
| 新版本发布 | ❌ | ✅ `new-version.sh` |
| 发布 / 删除前确认 | ❌ | ✅ |
| 可复制即用的 `curl` + `jq` 示例 | ❌ | ✅ |

## 前置条件

- `curl`
- `jq`
- 所有涉及 `/account/...` 或上传的操作需要 [Figshare Personal Token](https://figshare.com/account/applications)：

  ```bash
  export FIGSHARE_TOKEN=xxxxxxxxxxxxxxxx
  ```

公开搜索 / 获取文章 / 下载不需要 token。

## 安装

### Claude Code

```bash
# 全局安装（所有项目可用）
git clone https://github.com/Agents365-ai/figshare-skill.git ~/.claude/skills/figshare-skill

# 项目级安装
git clone https://github.com/Agents365-ai/figshare-skill.git .claude/skills/figshare-skill
```

### OpenClaw

```bash
git clone https://github.com/Agents365-ai/figshare-skill.git ~/.openclaw/skills/figshare-skill

# 项目级
git clone https://github.com/Agents365-ai/figshare-skill.git skills/figshare-skill
```

### SkillsMP

在 [SkillsMP](https://skillsmp.com) 搜索或使用 CLI：

```bash
skills install figshare-skill
```

### 安装路径汇总

| 平台 | 全局路径 | 项目路径 |
|------|----------|----------|
| Claude Code | `~/.claude/skills/figshare-skill/` | `.claude/skills/figshare-skill/` |
| OpenClaw | `~/.openclaw/skills/figshare-skill/` | `skills/figshare-skill/` |
| SkillsMP | N/A（CLI 安装） | N/A |

## 使用示例

直接描述你想做什么：

```
> 在 figshare 上搜索 "single cell" 数据集，返回前 10 条

> 把 https://figshare.com/articles/dataset/xxx/31957606 的全部文件下载到 ./data

> 把 ./results.zip 上传到我的草稿文章 31957803

> 为已发布文章 12345678 创建并发布一个新版本，新文件是 ./v2.csv
```

技能会自动选对端点、补齐认证，并调用内置脚本完成多分片上传。

## 辅助脚本

| 脚本 | 用途 |
|------|------|
| `scripts/upload.sh <article_id> <file>` | 三步式多分片上传到草稿文章 |
| `scripts/download.sh <id_or_url> [dir]` | 公开文章批量下载 |
| `scripts/new-version.sh <article_id> <file>` | 预留、上传并发布新版本 |

全部脚本从环境变量读取 `FIGSHARE_TOKEN`，只依赖 `curl` 与 `jq`。

## 文件说明

- `SKILL.md` —— **唯一必需的文件**，所有平台都会加载它作为技能指令
- `scripts/upload.sh` —— 多分片上传
- `scripts/download.sh` —— 批量下载
- `scripts/new-version.sh` —— 新版本工作流
- `README.md` —— 英文文档（GitHub 首页展示）
- `README_CN.md` —— 本文件

## 已知限制

- **`dd bs=1` 在极大分片上偏慢**：数 GB 以内的分片没问题，单文件超大场景建议改为 `bs=1M` + `skip=`/`count=`
- **速率限制**：Figshare 未公布硬限，但建议 ≤1 req/sec，脚本未内置节流
- **已发布版本不可修改**：修改内容必须走 `new-version.sh`，不能 `update`
- **Categories / licenses 是数字 ID**：创建文章前用 `GET /v2/categories` 和 `GET /v2/licenses` 查表

## License

MIT

## 赞赏

如果这个技能对你有帮助，欢迎赞赏作者：

<table>
  <tr>
    <td align="center">
      <img src="https://raw.githubusercontent.com/Agents365-ai/images_payment/main/qrcode/wechat-pay.png" width="180" alt="微信支付">
      <br>
      <b>微信支付</b>
    </td>
    <td align="center">
      <img src="https://raw.githubusercontent.com/Agents365-ai/images_payment/main/qrcode/alipay.png" width="180" alt="支付宝">
      <br>
      <b>支付宝</b>
    </td>
    <td align="center">
      <img src="https://raw.githubusercontent.com/Agents365-ai/images_payment/main/qrcode/buymeacoffee.png" width="180" alt="Buy Me a Coffee">
      <br>
      <b>Buy Me a Coffee</b>
    </td>
  </tr>
</table>

## 作者

**Agents365-ai**

- Bilibili: https://space.bilibili.com/441831884
- GitHub: https://github.com/Agents365-ai


path: scripts/download.sh
content: #!/usr/bin/env bash
# Download all files from a public Figshare article.
# Usage: ./download.sh <article_id|figshare_url> [output_dir]
set -euo pipefail

ARG="${1:?article_id or figshare URL required}"
OUT="${2:-.}"
mkdir -p "$OUT"

# Accept a figshare.com URL and extract the numeric id from the tail.
ART=$(echo "$ARG" | grep -oE '[0-9]+' | tail -1)
[ -n "$ART" ] || { echo "could not parse article id from: $ARG" >&2; exit 1; }

echo ">> article $ART"
curl -sS "https://api.figshare.com/v2/articles/$ART/files" \
  | jq -r '.[] | "\(.download_url)\t\(.name)"' \
  | while IFS=$'\t' read -r url name; do
      echo "   downloading $name"
      curl -L -sS -o "$OUT/$name" "$url"
    done
echo ">> done -> $OUT"


path: scripts/new-version.sh
content: #!/usr/bin/env bash
# Create a new version of a published Figshare article by reserving a version
# and uploading a new file. Published versions are frozen, so edits require
# a new version.
#
# Usage: ./new-version.sh <article_id> <file_path>
# Requires: FIGSHARE_TOKEN, curl, jq, and scripts/upload.sh next to this file.
set -euo pipefail

ART="${1:?article_id required}"
FILE="${2:?file path required}"
: "${FIGSHARE_TOKEN:?FIGSHARE_TOKEN not set}"

API="https://api.figshare.com/v2"
AUTH=(-H "Authorization: token $FIGSHARE_TOKEN")
HERE="$(cd "$(dirname "$0")" && pwd)"

echo ">> reserving new version for article $ART"
# Reserving a DOI on the next version creates a pending draft you can edit.
curl -sS -X POST "${AUTH[@]}" "$API/account/articles/$ART/reserve_doi" >/dev/null || true

echo ">> uploading $FILE to article $ART (draft version)"
bash "$HERE/upload.sh" "$ART" "$FILE"

echo ">> publishing new version"
curl -sS -o /dev/null -w "publish status: %{http_code}\n" \
  -X POST "${AUTH[@]}" "$API/account/articles/$ART/publish"


path: scripts/upload.sh
content: #!/usr/bin/env bash
# Upload a file to a Figshare article using the 3-step multi-part flow.
# Usage: ./upload.sh <article_id> <file_path>
# Requires: FIGSHARE_TOKEN env var, curl, jq, md5sum (or md5 on macOS).
set -euo pipefail

ART="${1:?article_id required}"
FILE="${2:?file path required}"
: "${FIGSHARE_TOKEN:?FIGSHARE_TOKEN not set}"

API="https://api.figshare.com/v2"
AUTH=(-H "Authorization: token $FIGSHARE_TOKEN")

[ -f "$FILE" ] || { echo "file not found: $FILE" >&2; exit 1; }

NAME=$(basename "$FILE")
if stat -f%z "$FILE" >/dev/null 2>&1; then SIZE=$(stat -f%z "$FILE"); else SIZE=$(stat -c%s "$FILE"); fi
if command -v md5sum >/dev/null 2>&1; then MD5=$(md5sum "$FILE" | awk '{print $1}'); else MD5=$(md5 -q "$FILE"); fi

echo ">> initiating upload: name=$NAME size=$SIZE md5=$MD5"
INIT=$(curl -sS -X POST "$API/account/articles/$ART/files" "${AUTH[@]}" \
  -H "Content-Type: application/json" \
  -d "{\"md5\":\"$MD5\",\"name\":\"$NAME\",\"size\":$SIZE}")
LOC=$(echo "$INIT" | jq -r '.location')
[ "$LOC" != "null" ] || { echo "init failed: $INIT" >&2; exit 1; }

FILE_INFO=$(curl -sS "${AUTH[@]}" "$LOC")
UPLOAD_URL=$(echo "$FILE_INFO" | jq -r '.upload_url')
FILE_ID=$(echo "$FILE_INFO" | jq -r '.id')
echo ">> file_id=$FILE_ID upload_url=$UPLOAD_URL"

PARTS=$(curl -sS "${AUTH[@]}" "$UPLOAD_URL")
NPARTS=$(echo "$PARTS" | jq '.parts | length')
echo ">> uploading $NPARTS part(s)"

echo "$PARTS" | jq -c '.parts[]' | while read -r part; do
  NO=$(echo "$part" | jq -r '.partNo')
  START=$(echo "$part" | jq -r '.startOffset')
  END=$(echo "$part" | jq -r '.endOffset')
  LEN=$((END - START + 1))
  echo "   part $NO: bytes $START-$END ($LEN)"
  dd if="$FILE" bs=1 skip="$START" count="$LEN" status=none \
    | curl -sS -X PUT --data-binary @- "${AUTH[@]}" "$UPLOAD_URL/$NO" >/dev/null
done

echo ">> completing upload"
# Figshare returns 202 with an HTML body; we only care about the status code.
CODE=$(curl -sS -o /dev/null -w "%{http_code}" -X POST "${AUTH[@]}" "$API/account/articles/$ART/files/$FILE_ID")
if [ "$CODE" != "200" ] && [ "$CODE" != "202" ]; then
  echo "complete failed: HTTP $CODE" >&2; exit 1
fi
echo ">> done: file_id=$FILE_ID (HTTP $CODE)"


Security scan verdicts — ClawScan: suspicious | static analysis: clean | VirusTotal: clean | SkillSpector: suspicious (CRITICAL)