From hf2ms
This skill should be used when the user wants to migrate, transfer, copy, or mirror repos between HuggingFace and ModelScope using Modal. Triggers on "migrate model to ModelScope", "transfer dataset to HuggingFace", "copy from HF to MS", "mirror repo", "move to modelscope", "batch migrate multiple repos", "parallel migration", "detached migration", "fire and forget", "verify migration integrity", or "clean up org after migration".
How this skill is triggered — by the user, by Claude, or both
Slash command
/hf2ms:migrateThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Migrate repos between HuggingFace and ModelScope using Modal as an ephemeral cloud compute bridge. No files touch the local machine — everything transfers cloud-to-cloud.
Migrate repos between HuggingFace and ModelScope using Modal as an ephemeral cloud compute bridge. No files touch the local machine — everything transfers cloud-to-cloud.
Local Machine Modal Container Platforms
┌──────────┐ modal run ┌─────────────────┐ API ┌──────────┐
│ Claude │ ──────────> │ snapshot_download│ <──────> │ HF Hub │
│ Code │ │ OR git clone │ │ │
│ │ │ upload_folder │ <──────> │ MS Hub │
└──────────┘ └─────────────────┘ └──────────┘
Each migration spins up a fresh Modal container, transfers files via platform SDKs, then destroys the container. No persistent storage between runs.
huggingface_hub.snapshot_download (auto-falls back to git clone + git lfs pull if API returns 403). Upload via ModelScope HubApi.upload_folder()modelscope.hub.snapshot_download, upload via HfApi.upload_folder()Single container downloads the entire repo, then uploads it. Tested up to 58.5 GB; 24-hour timeout supports larger repos. Use --parallel for anything over ~50 GB.
--parallel)Splits the repo into chunks, each processed by an independent container. Up to 100 containers run concurrently. Each chunk worker: clones repo structure (no LFS data) -> selectively pulls its assigned LFS files -> uploads to destination. Best for repos over 50 GB.
┌─ Container 0: clone + pull chunk 0 + upload ─┐
HuggingFace ────────┼─ Container 1: clone + pull chunk 1 + upload ─┼──── ModelScope
(source) ├─ Container 2: clone + pull chunk 2 + upload ─┤ (dest)
└─ ...up to 100 concurrent containers... ┘
Guardrails:
These features run automatically — no flags needed:
git clone + git lfs pull.--parallel for larger repos.| Type | HF -> MS | MS -> HF | Notes |
|---|---|---|---|
| Models | Yes | Yes | Weights, configs, tokenizers |
| Datasets | Yes | Yes | Data files, metadata |
| Spaces | Skipped (warning) | N/A | ModelScope Studios are web/git only — SDK has no support |
Three sets of credentials must be available as environment variables:
| Variable | Platform | How to Get |
|---|---|---|
HF_TOKEN | HuggingFace | https://huggingface.co/settings/tokens (needs read + write) |
MODAL_TOKEN_ID | Modal | Run modal token new or https://modal.com/settings |
MODAL_TOKEN_SECRET | Modal | Same as above |
MODELSCOPE_TOKEN | ModelScope | https://modelscope.ai/my/myaccesstoken |
MODELSCOPE_DOMAIN | ModelScope (optional) | Defaults to modelscope.cn. Set to modelscope.ai for international site. |
Tokens can be set in the shell or placed in ${CLAUDE_PLUGIN_ROOT}/.env — the validation script and /migrate command auto-load this file. Install huggingface_hub and modelscope locally for token validation. The migration itself runs entirely on Modal.
Use the /migrate command for the guided interactive workflow. It handles token validation, parameter extraction, user confirmation, and execution.
For direct CLI usage, all commands below use this prefix (sources .env and prevents Unicode errors on Windows):
PREFIX="set -a && source \"${CLAUDE_PLUGIN_ROOT}/.env\" 2>/dev/null; set +a; PYTHONIOENCODING=utf-8"
Single repo:
eval $PREFIX modal run "${CLAUDE_PLUGIN_ROOT}/scripts/modal_migrate.py::main" --source "username/my-model" --to ms
Parallel chunked (large repos):
eval $PREFIX modal run "${CLAUDE_PLUGIN_ROOT}/scripts/modal_migrate.py::main" --source "org/big-dataset" --to ms --repo-type dataset --parallel --chunk-size 30
Batch (one container per repo):
eval $PREFIX modal run "${CLAUDE_PLUGIN_ROOT}/scripts/modal_migrate.py::batch" --source "user/model1,user/model2" --to ms --repo-type model
Detached (fire & forget):
eval $PREFIX modal run --detach "${CLAUDE_PLUGIN_ROOT}/scripts/modal_migrate.py::main" --source "username/my-model" --to ms
| Aspect | Single (::main) | Batch (::batch) |
|---|---|---|
--source | One repo ID | Comma-separated list |
--dest | Supported | NOT supported |
| Existing repos | Warns, proceeds | Auto-skips |
Batch mode uses the source repo ID as the destination. If the HF org name differs from the MS org name, use individual ::main runs with --dest.
Add --detach before the script path. The migration continues in Modal's cloud after the session ends. Monitor with modal app logs hf-ms-migrate or the Modal dashboard.
git clone + git lfs pull.--repo-type model (only files transfer, not the app runtime).--parallel. Tested up to 58.5 GB single-container and 3.3 TB parallel (113 chunks).--parallel. Chunk size auto-adjusts to keep within 100 chunks (e.g., 3.3 TB -> ~30 GB chunks -> 113 chunks, processed in waves of up to 100 concurrent containers).--dest. If source org differs from dest org, use individual ::main runs with --dest.| Error Pattern | Suggestion |
|---|---|
| "not set" or "token" | Re-check tokens: python "${CLAUDE_PLUGIN_ROOT}/scripts/validate_tokens.py" |
| "not found" or "404" | Verify the repo ID exists on the source platform |
| "403" or "Forbidden" | Usually auto-handled (falls back to git clone). If persistent, check token permissions |
| "timeout" | Use --parallel for large repos, or --repo-type to skip auto-detect |
| "Modal" or "container" | Check Modal account: modal token verify |
| "upload" errors | Check MODELSCOPE_TOKEN permissions |
| "Unauthorized" | Namespace mismatch — use ::main with --dest instead of batch |
For SHA256 cross-platform verification and org cleanup workflows (inventory, verify, migrate-then-delete), read: ${CLAUDE_PLUGIN_ROOT}/skills/migrate/references/verification-and-cleanup.md
| Script | Purpose | Run As |
|---|---|---|
${CLAUDE_PLUGIN_ROOT}/scripts/modal_migrate.py | Modal app with migration functions | modal run ... |
${CLAUDE_PLUGIN_ROOT}/scripts/validate_tokens.py | Check all platform tokens | python ... |
${CLAUDE_PLUGIN_ROOT}/scripts/utils.py | Shared helpers (imported by other scripts) | N/A (library) |
Before searching the web for HuggingFace or ModelScope SDK methods, read the bundled reference file. It contains complete Python SDK signatures for both platforms (list, info, create, download, upload, files, branches) and a key differences table.
Read first: ${CLAUDE_PLUGIN_ROOT}/skills/migrate/references/hub-api-reference.md
npx claudepluginhub linaqruf/hf2msCLI for Hugging Face Hub: download/upload models, datasets, spaces; manage repos, buckets, jobs, endpoints, and auth.
Runs Hugging Face Hub CLI (`hf`) to download/upload models/datasets/Spaces, manage authentication, repos, and buckets. Useful for Hub interactions in AI/ML projects.
Pushes and publishes AI models to Replicate with cog push or cog-safe-push for CI/CD and safe version releases. Useful when deploying a model, releasing versions, or setting up GitHub Actions for model releases.