# How to Fork Existing Hugging Face Spaces Environments for Customization with OpenEnv

> Customize Hugging Face Spaces easily. Use OpenEnv's `openenv fork` command to duplicate and modify hardware, privacy, and environment variables in one step.

- Repository: [Hugging Face/OpenEnv](https://github.com/huggingface/OpenEnv)
- Tags: how-to-guide
- Published: 2026-06-14

---

**OpenEnv provides the `openenv fork` CLI command that wraps the Hugging Face Hub API `duplicate_space` method to duplicate existing Spaces while allowing you to customize hardware, privacy settings, environment variables, and secrets in a single operation.**

The `openenv fork` command streamlines the process of duplicating and customizing Hugging Face Spaces environments without manual configuration through the web interface. Located in [`src/openenv/cli/commands/fork.py`](https://github.com/huggingface/OpenEnv/blob/main/src/openenv/cli/commands/fork.py), this Typer-based CLI tool handles authentication, payload construction, and API communication automatically. This guide explains how to fork existing Hugging Face Spaces environments for customization with OpenEnv, covering the internal architecture, command-line options, and the complete workflow from duplication to deployment.

## Understanding the openenv fork Architecture

The fork functionality is implemented as a modular command following OpenEnv's CLI patterns. The implementation resides in [`src/openenv/cli/commands/fork.py`](https://github.com/huggingface/OpenEnv/blob/main/src/openenv/cli/commands/fork.py) and integrates with the Hugging Face Hub API through the `HfApi` class.

### Core Implementation in fork.py

The `fork()` function serves as the entry point for the command. It parses command-line arguments, constructs a `dup_kwargs` dictionary, and invokes `api.duplicate_space()`. The function validates the source Space identifier (format `owner/space-name`) and ensures all optional parameters are properly formatted before making the API call.

The CLI registration occurs at lines 86-131 in the same file, where the `fork` sub-command is added to the main Typer application via `app.command()`. This registration exposes the command through the root CLI entry point in [`src/openenv/cli/__main__.py`](https://github.com/huggingface/OpenEnv/blob/main/src/openenv/cli/__main__.py).

### Authentication and Session Management

Before executing the fork operation, the command ensures active Hugging Face authentication through the `_ensure_hf_authenticated()` helper (lines 37-83). This function first attempts to verify the session via `whoami()`. If no valid session exists, it automatically triggers `login()` from the `huggingface_hub` library. This design ensures the command works seamlessly in both interactive environments and CI pipelines where tokens may be pre-configured.

### API Payload Construction

The command builds a `dup_kwargs` dictionary that translates CLI arguments into the JSON payload expected by `HfApi.duplicate_space`. When you specify `--set-env` or `--set-secret`, the `_parse_key_value()` helper (lines 23-34) validates the `KEY=VALUE` syntax. These values are then formatted as lists of `{"key":..., "value":...}` objects to match the Hub API contract.

The `--hardware` parameter defaults to `"cpu-basic"` (the free tier) when not specified, ensuring the fork succeeds even if the original Space required paid hardware. The function only includes explicitly provided arguments in the payload, preventing unintended overwrites of default configurations.

## How to Fork Existing Hugging Face Spaces for Customization

The `openenv fork` command supports multiple configuration options to customize the duplicated Space during creation.

### Basic Fork Operation

To duplicate a public Space to your account while maintaining the original name:

```bash
openenv fork huggingface/openenv-echo

```

This creates a new Space at `https://huggingface.co/spaces/<your-username>/openenv-echo` using the default `cpu-basic` hardware tier.

### Customizing Privacy and Hardware

To create a private fork with specific GPU resources:

```bash
openenv fork huggingface/openenv-echo \
    --private \
    --hardware t4-medium

```

The `--private` flag restricts visibility to your account, while `--hardware` accepts tier identifiers like `cpu-basic`, `t4-medium`, or `t4-large` depending on your Hugging Face subscription.

### Specifying Environment Variables and Secrets

You can pre-configure variables and secrets during the fork operation:

```bash
openenv fork huggingface/openenv-echo \
    --repo-id myuser/custom-echo \
    --set-env MODEL_ID=google/flan-t5-large \
    --set-secret HF_TOKEN=hf_XXXXXXXXXXXXXXXXX

```

The `--repo-id` parameter allows you to specify a custom target repository ID (format: `username/space-name`). The `--set-env` flag creates visible environment variables in the Space settings UI, while `--set-secret` stores encrypted values accessible only to the application runtime. Both flags accept multiple `KEY=VALUE` pairs validated by the `_parse_key_value()` internal function.

## Complete Workflow: Fork, Customize, and Push

After forking, you typically customize the environment code and push updates back to the Space:

```bash

# 1. Fork the original Space to your account

openenv fork huggingface/openenv-echo --repo-id myuser/echo-fork

# 2. Clone the newly forked repository

git clone https://huggingface.co/spaces/myuser/echo-fork
cd echo-fork

# 3. Modify environment files (e.g., edit envs/echo_env/server/app.py)

# 4. Push changes back to the Space

openenv push

```

Once `openenv push` completes, the Space automatically reloads with your customizations. This workflow leverages the same authentication mechanisms used during the fork operation, ensuring seamless integration between the CLI commands.

## Summary

- **Use `openenv fork`** to duplicate Hugging Face Spaces via the `duplicate_space` Hub API, implemented in [`src/openenv/cli/commands/fork.py`](https://github.com/huggingface/OpenEnv/blob/main/src/openenv/cli/commands/fork.py).
- **Authentication is automatic** through `_ensure_hf_authenticated()`, which verifies your session or prompts for login as needed.
- **Hardware defaults to `cpu-basic`** but can be upgraded via `--hardware` to avoid paid tier requirements during initial duplication.
- **Variables and secrets** are parsed by `_parse_key_value()` and formatted as JSON objects matching the Hub API contract.
- **After forking**, use standard git workflows combined with `openenv push` to deploy code changes to your customized Space.

## Frequently Asked Questions

### What authentication does openenv fork require?

The command automatically handles authentication through the `_ensure_hf_authenticated()` function in [`src/openenv/cli/commands/fork.py`](https://github.com/huggingface/OpenEnv/blob/main/src/openenv/cli/commands/fork.py). It first checks for an active session using `whoami()`, and if none exists, triggers `login()` from the `huggingface_hub` library. This ensures you have valid API access before attempting to duplicate the Space.

### Can I fork a Space to a different repository name?

Yes. Use the `--repo-id` parameter to specify a custom target identifier in the format `username/space-name`. If you omit this parameter, the command uses the original Space name under your authenticated account. This allows you to maintain multiple customized versions of the same base environment.

### How do I change hardware after forking?

You can specify hardware during the fork using the `--hardware` flag (e.g., `--hardware t4-medium`). If you need to change hardware after creation, you must use the Hugging Face Spaces web interface or API to modify the Space settings, as the `openenv fork` command only sets the initial configuration during duplication.

### What is the difference between --set-env and --set-secret?

The `--set-env` flag creates environment variables visible in the Space Settings UI, suitable for non-sensitive configuration like model IDs or API endpoints. The `--set-secret` flag stores values as encrypted secrets hidden from the interface, designed for API keys and tokens. Both use `KEY=VALUE` syntax validated by the `_parse_key_value()` helper function.