Skip to content

[CLI] Add hf spaces duplicate command#4197

Open
davanstrien wants to merge 4 commits intohuggingface:mainfrom
davanstrien:cli-spaces-duplicate
Open

[CLI] Add hf spaces duplicate command#4197
davanstrien wants to merge 4 commits intohuggingface:mainfrom
davanstrien:cli-spaces-duplicate

Conversation

@davanstrien
Copy link
Copy Markdown
Member

@davanstrien davanstrien commented May 6, 2026

Adds hf spaces duplicate <from_id> [<to_id>] so duplicate sits alongside the other hf spaces lifecycle/management commands (pause, restart, settings, secrets, variables, volumes, card, logs, hardware).

hf spaces duplicate username/my-space
hf spaces duplicate username/my-space my-copy --private
hf spaces duplicate username/my-space my-copy --hardware l4x4 --secrets HF_TOKEN -v hf://buckets/org/b:/data

Design notes

  • Wraps duplicate_repo, not duplicate_space — the latter is @_deprecate_method(version="2.0", ...) at hf_api.py:8468. duplicate_repo already plumbs through all the Space-specific args.
  • Why a new command when hf repos duplicate --type space exists? Same rationale as hf spaces card ([CLI] Add hf models card and hf datasets card commands #4118): per-type ergonomic wrapper keeps the spaces namespace internally consistent.
  • Flag names--hardware, --sleep-time match hf spaces settings ([CLI] Add --hardware flag to hf spaces settings #4163), not --flavor from hf repos duplicate. Internal-namespace consistency over cross-namespace mirror.
  • Flag set is a full mirror of hf repos duplicate minus --type.
  • PublicOpt / ProtectedOpt are copy-pasted verbatim from cli/repos.py:77–91. Could be lifted to _cli_utils.py for one source of truth — happy to do that as a small follow-up.
  • No tests per [CLI] Add spaces lifecycle commands: pause, restart, sleep #4155 review feedback. No confirmation prompt — duplicate is creation, not destruction.

Hint chain

After a successful duplicate:

Hint: Use `hf spaces info <to_id>` to monitor the runtime stage.
Hint: Source secrets and variables are not copied. Run `hf spaces secrets ls <from_id>`
      and `hf spaces variables ls <from_id>` to see what to set on the new Space.

secrets ls / variables ls already emit hints with the add syntax, so an agent chains through without this command pre-fetching anything.

Smoke test

$ hf spaces duplicate multimodalart/dreambooth-training davanstrien/duplicate-smoke-test --private
# 400: "Hardware must be specified when duplicating a Space"  ← server validation surfaces cleanly

$ hf spaces duplicate multimodalart/dreambooth-training davanstrien/duplicate-smoke-test --private --hardware cpu-basic
# Space duplicated  + hint chain renders correctly

# Carry-over check:
$ hf spaces variables add davanstrien/duplicate-smoke-test -e CARRY_TEST_VAR=hello
$ hf spaces secrets   add davanstrien/duplicate-smoke-test -s CARRY_TEST_SECRET=shh
$ hf spaces duplicate davanstrien/duplicate-smoke-test davanstrien/duplicate-carry-test-2 --private --hardware cpu-basic
$ hf spaces variables ls davanstrien/duplicate-carry-test-2   # → no results
$ hf spaces secrets   ls davanstrien/duplicate-carry-test-2   # → no results
# Confirmed: secrets and variables do not carry over from source.

Found while testing (separate follow-up)

duplicate_repo (hf_api.py:8466) crashes with KeyError: 'url' when exist_ok=True hits a 409 — the swallow path falls through to r.json()["url"] on what's actually an error body. Independent of this PR; will open a separate fix.


Note

Medium Risk
Adds a new CLI surface that creates/duplicates Spaces and forwards many runtime/visibility/env options to the Hub API, so mistakes could create misconfigured or incorrectly visible Spaces. Changes are localized to CLI wiring and docs, with no core auth or data-path refactors.

Overview
Adds a new hf spaces duplicate FROM_ID [TO_ID] command that wraps HfApi.duplicate_repo(..., repo_type="space"), supporting visibility flags plus Space runtime overrides like --hardware, --sleep-time, deprecated --storage, and optional secrets/vars/volume mounts.

Updates the CLI guide and generated CLI reference to document the new command and its flags, and prints post-run hints (including that source secrets/variables are not copied).

Reviewed by Cursor Bugbot for commit 20ba280. Bugbot is set up for automated code reviews on this repo. Configure here.

Adds `hf spaces duplicate <from_id> [<to_id>]` so duplicate sits alongside
the other `hf spaces` lifecycle/management commands. Wraps `duplicate_repo`
with `repo_type` locked to `"space"`; `duplicate_space` is deprecated for
v2.0 and not used.

Flag set mirrors `hf repos duplicate` minus `--type`. Flag names match
`hf spaces settings` (`--hardware`, `--sleep-time`) for namespace
consistency.

Post-duplicate hints point at `hf spaces info`, `secrets ls`, and
`variables ls` so agents can chain through to discover what needs to be
set on the new Space.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@bot-ci-comment
Copy link
Copy Markdown

bot-ci-comment Bot commented May 6, 2026

The docs for this PR live here. All of your documentation changes will be reflected on that endpoint. The docs are available until 30 days after the last update.

davanstrien and others added 3 commits May 6, 2026 14:40
Auto-generated by `python utils/generate_cli_reference.py --update`.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- from_id/to_id help text uses lowercase "space" to match other
  cli/spaces.py argument conventions.
- exist_ok mirrors `cli/repos.py` wording verbatim ("if repo already
  exists").

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Move "Duplicate a Space" from between "Update Space settings" and
"Manage Space secrets" to right after "Get Space card".

The new order is discovery → create → operate → configure:
ls → info → card → duplicate → pause → restart → hardware → settings →
secrets → variables.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@davanstrien davanstrien marked this pull request as ready for review May 6, 2026 14:01
@davanstrien davanstrien requested a review from Wauplin May 6, 2026 14:01
@codecov
Copy link
Copy Markdown

codecov Bot commented May 6, 2026

Codecov Report

❌ Patch coverage is 50.00000% with 5 lines in your changes missing coverage. Please review.
✅ Project coverage is 77.14%. Comparing base (1daa48b) to head (20ba280).
⚠️ Report is 327 commits behind head on main.

Files with missing lines Patch % Lines
src/huggingface_hub/cli/spaces.py 50.00% 5 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #4197      +/-   ##
==========================================
+ Coverage   75.00%   77.14%   +2.14%     
==========================================
  Files         145      170      +25     
  Lines       13978    19437    +5459     
==========================================
+ Hits        10484    14995    +4511     
- Misses       3494     4442     +948     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant