Skip to content

[CLI] Add hf spaces secrets and variables subgroups#4170

Merged
Wauplin merged 6 commits intomainfrom
cli-spaces-secrets-variables
May 4, 2026
Merged

[CLI] Add hf spaces secrets and variables subgroups#4170
Wauplin merged 6 commits intomainfrom
cli-spaces-secrets-variables

Conversation

@davanstrien
Copy link
Copy Markdown
Member

@davanstrien davanstrien commented Apr 29, 2026

Summary

Adds two nested subgroups under hf spaces, mirroring volumes per the #4155 thread:

  • hf spaces secrets {add,delete}add_space_secret / delete_space_secret
  • hf spaces variables {add,delete,ls}add_space_variable / delete_space_variable / get_space_variables

Both add commands accept multiple -s/-e flags and --secrets-file/--env-file (dotenv), reusing the existing parse_env_map helper — no new parsing code.

Examples (smoke-tested on a live Space)

$ hf spaces variables add me/space -e MODEL_ID=gpt2 -e MAX_TOKENS=512
✓ Variables added
  keys: ['MODEL_ID', 'MAX_TOKENS']

$ hf spaces variables ls me/space
KEY        VALUE  UPDATED_AT
---------- ------ ----------
MODEL_ID   gpt2   2026-04-30
MAX_TOKENS 512    2026-04-30

$ hf spaces variables delete me/space MAX_TOKENS
You are about to remove variable 'MAX_TOKENS' from Space 'me/space'. Proceed? [y/N]: y
✓ Variable deleted

$ hf spaces secrets delete me/space OPENAI_API_KEY
You are about to remove secret 'OPENAI_API_KEY' from Space 'me/space'. The value cannot be recovered. Proceed? [y/N]: y
✓ Secret deleted

Design notes

  • add (not set) — mirrors the underlying add_space_secret / add_space_variable API verbs and signals upsert semantics explicitly (vs volumes set, which is replace-all).
  • Confirm + --yes on both delete commands. Per @Wauplin's review — consistency over micro-optimization.
  • Confirm message phrasing is deliberately asymmetric. secrets delete warns "...The value cannot be recovered." because the Hub never exposes secret values. variables delete uses the shorter volumes-style "...Proceed?" because variable values are visible via ls before deletion, so a "cannot be recovered" warning would be misleading.
  • No secrets ls — Hub exposes secrets as write-only (no GET endpoint). Will land in a follow-up here once @Wauplin's moon-landing PR exposes secret keys.
  • Verb is delete to match every other destructive command in the CLI.
  • No new tests — matches [CLI] Add hf spaces volumes commands #4109 (volumes) and [CLI] Add spaces lifecycle commands: pause, restart, sleep #4155 (lifecycle) precedent for thin HfApi wrappers. Parsing is covered by existing parse_env_map tests via jobs run / repos create.
  • Both delete_space_secret and delete_space_variable are idempotent server-side — deleting a non-existent key returns success, not 4xx.

Note

Medium Risk
Introduces new CLI surface area that mutates Space configuration and handles secret values, so mistakes could overwrite or delete environment settings. Implementation is thin wrappers over existing API calls with confirmation prompts on destructive actions.

Overview
Adds two new hf spaces subgroups: secrets (supports add/delete) and variables (supports ls/add/delete) to manage a Space’s secret and non-secret environment variables via HfApi.

Both add commands accept repeated flags and dotenv-style files (--secrets-file / --env-file) via existing parse_env_map, and both delete commands add confirmation prompts with --yes. Documentation and the generated CLI reference are updated to describe the new commands and the write-only nature of secrets (no secrets ls).

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

@bot-ci-comment
Copy link
Copy Markdown

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 davanstrien marked this pull request as ready for review April 29, 2026 13:48
@davanstrien davanstrien requested review from Wauplin and hanouticelina and removed request for Wauplin April 29, 2026 15:52
@Wauplin
Copy link
Copy Markdown
Contributor

Wauplin commented Apr 30, 2026

Hi @davanstrien , haven't reviewed the code yet but to answer the "design notes" from the PR description:

No secrets ls — Hub exposes secrets as write-only (no GET endpoint). Called out in the CLI guide.

It would actually make sense to expose secrets keys even if values are hidden. Currently not possible in the API but I'll open a PR in moon-landing for that. Can be addressed in a later PR in huggingface_hub (but let's not forget about it)

Confirm + --yes on secrets delete only. Per the #4155 rule ("yolo when nothing's hard-deleted"): secret values are unrecoverable; variable values are replayable from ls.

I would confirm + -y/--yes on both delete commands. Variable values are not recoverable after deletion so it's the same problem as secrets. Besides, it'll make the CLI consistent between secrets and variables which is good

set is upsert, not replace. Forced by the API (one key per call, no bulk endpoint). Differs from volumes set.

Then maybe hf spaces variables add and hf spaces secrets add are better suited to be explicit on the "upsert, not replace" behavior. Plus it follows the existing add_space_secret / add_space_variable API

Verb is delete to match every other destructive command in the CLI.

Good 👍

No new tests

ok 👍

Hub's secret-delete is idempotent — deleting a non-existent key returns success.

out of curiosity, what about variables?

davanstrien and others added 2 commits April 30, 2026 10:46
- `hf spaces secrets {set,delete}` wraps add_space_secret / delete_space_secret.
- `hf spaces variables {set,delete,ls}` wraps add/delete_space_variable and get_space_variables.
- Both `set` commands accept multiple `-s`/`-e` flags and `--secrets-file`/`--env-file`
  (dotenv) via the existing `parse_env_map` helper — no new parsing code.
- No `secrets ls`: Hub exposes secrets as write-only (no GET endpoint).
- Confirm + `--yes` on `secrets delete` only (lost-value risk); variables delete is
  replayable so it skips the prompt, per the #4155 rule.
- `set` is upsert (one API call per key — no bulk endpoint), not replace-collection.

Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
- Rename `secrets set` / `variables set` to `add` (mirrors add_space_secret/
  add_space_variable, signals upsert vs volumes set's replace).
- Add confirm + `-y/--yes` to `variables delete` for parity with
  `secrets delete`. Kept the warning text intentionally asymmetric: secrets
  says "value cannot be recovered" (true: write-only API), variables uses
  the shorter volumes-style phrasing (the value is visible via `ls` before
  deletion).
- Remove now-stale per-command `--format` declarations. #4162 made --format
  global, so these were dead code that was breaking the import after the
  rebase.

Per @Wauplin review at #4170 (comment 4351208819).

Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
@davanstrien davanstrien force-pushed the cli-spaces-secrets-variables branch from 23133f2 to 55fda90 Compare April 30, 2026 10:20
@davanstrien
Copy link
Copy Markdown
Member Author

Thanks @Wauplin - applied all three:

  • Renamed setadd for both subgroups. Reads better and lines up with add_space_secret / add_space_variable.
  • Confirm + -y/--yes now on variables delete too. Kept the warning text slightly different between the two (secrets says "the value cannot be recovered", variables doesn't, since variable values are visible via ls before deletion). Happy to flip to strict text symmetry if you'd prefer though?
  • secrets ls left as a follow up

re: idempotent delete on variables both have same behaviour:

  • delete_space_variable("DOES_NOT_EXIST") → returns {} (empty remaining-vars dict), no exception
  • delete_space_secret("DOES_NOT_EXIST") → returns None, no exception

Copy link
Copy Markdown
Contributor

@Wauplin Wauplin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you!

Comment thread docs/source/en/guides/cli.md Outdated
Comment thread src/huggingface_hub/cli/spaces.py Outdated
@Wauplin Wauplin merged commit 1f2efa5 into main May 4, 2026
21 checks passed
@Wauplin Wauplin deleted the cli-spaces-secrets-variables branch May 4, 2026 12:23
@huggingface-hub-bot
Copy link
Copy Markdown
Contributor

This PR has been shipped as part of the v1.14.0 release.

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.

2 participants