> ## Documentation Index
> Fetch the complete documentation index at: https://praison.ai/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Hub Privacy & Upload Options

> Every praisonai-train Hub push is private by default — opt in to publish, tune the commit, tags, and save method

Every Hub push from `praisonai-train` is private by default. Set `hf_private: false` in `config.yaml` to publish.

<Warning>
  Prior to PraisonAI [PR #4357](https://github.com/MervinPraison/PraisonAI/pull/4357), every training run that set `huggingface_save: true` uploaded to a **public** repo, silently — LLM, vision, and standalone upload paths alike. From this release the default is **private**. If you were relying on the old behaviour, add `hf_private: false` to your config.

  Follow-up hardening in [PR #4367](https://github.com/MervinPraison/PraisonAI/pull/4367): the parser used to fail **open** — anything outside `{true, 1, yes, on}` was read as `false` and the repo was published. An unparseable value like `hf_private: enabled` now stays **private** and prints a warning.
</Warning>

<Note>
  **Vision publish-default parity (PraisonAI [#4879](https://github.com/MervinPraison/PraisonAI/pull/4879)).** Independent of `hf_private`, the vision trainer used to default `huggingface_save` / `huggingface_save_gguf` / `ollama_save` to ON (they read a config default of the string `"true"`), so a plain vision run pushed to the Hub even without those keys — private since #4357, but still a push the user never asked for, and a crash when `hf_model_name` was missing. From #4879 the vision path skips every publish stage unless the flag **and** its target are both set, matching the LLM trainer. See [Vision Fine-Tuning](/docs/features/praisonai-train-vision).
</Note>

```mermaid theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
graph LR
    subgraph "Hub push"
        C[⚙️ config.yaml] --> K[🔑 HF_TOKEN]
        K --> P{🔒 hf_private?}
        P -->|false, no, 0, off, n| Pub[🌐 Public repo]
        P -->|true, yes, 1, on, y, unset| Priv[🗝️ Private repo]
        P -->|anything else<br/>warn + keep| Priv
    end
    classDef in fill:#8B0000,stroke:#7C90A0,color:#fff
    classDef proc fill:#189AB4,stroke:#7C90A0,color:#fff
    classDef q fill:#F59E0B,stroke:#7C90A0,color:#fff
    classDef out fill:#10B981,stroke:#7C90A0,color:#fff
    class C in
    class K proc
    class P q
    class Priv,Pub out
```

## Quick Start

Publish to a public repo — opt out of the private default with one key.

```yaml theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
# config.yaml
model_name: unsloth/gemma-2-2b-it-bnb-4bit
hf_model_name: me/my-model         # namespaced, always
huggingface_save: true             # push after training
hf_private: false                  # opt-in to publish publicly
commit_message: "v0.1 from praisonai-train"
tags: ["praisonai", "gemma-2"]
```

```bash theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
praisonai train
```

Omit `hf_private` entirely and the repo is created **private** — the safe default.

## Config keys

Every key that shapes a Hub push, read from `_hub.py::hub_push_kwargs` and the trainer's `KNOWN_KEYS`.

| Key              | Type          | Default          | Description                                                                                                                                                                                |
| ---------------- | ------------- | ---------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `hf_private`     | bool          | `true`           | Push as a private repo, **fail-closed**. Publish only on `false, no, 0, off, n`; keep private on `true, yes, 1, on, y` (or unset). Any other value stays **private** and prints a warning. |
| `save_method`    | string        | `"merged_16bit"` | Passed to Unsloth's `push_to_hub_merged`. Previously hardcoded to `merged_16bit` at every push site.                                                                                       |
| `commit_message` | string        | —                | Optional commit message on the Hub. Only sent when set.                                                                                                                                    |
| `tags`           | list\[string] | —                | Optional tags on the Hub repo. Only sent when set.                                                                                                                                         |
| `hf_model_name`  | string        | required         | Hub repo id (e.g. `me/my-model`) — see the safety note below.                                                                                                                              |
| `hf_token`       | string        | —                | Config-level Hugging Face token. Overridden by the `HF_TOKEN` env var and a cached login. Also the download credential for gated base models.                                              |

### Accepted values for `hf_private`

`hf_private` fails **closed**: only the publish set opts out, and anything unrecognised stays private.

```text theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
Publish (private = false):   false   no   0   off   n
Keep private (private = true): true   yes  1   on   y     (also None / unset)
Anything else:               warn, keep PRIVATE
```

Any value outside those two sets — `"private"`, `"enabled"`, `5`, `""`, `"maybe"`, `[]` — keeps the repo private and prints:

```text theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
WARNING: hf_private='enabled' is not a yes/no value; keeping the repository PRIVATE. Use hf_private: false to publish.
```

<Note>
  `commit_message` and `tags` are only forwarded to the Hub when you set them — leave them out and nothing extra is sent.
</Note>

<Note>
  The fail-closed parser landed in PraisonAI [PR #4367](https://github.com/MervinPraison/PraisonAI/pull/4367). If you upgraded past #4357 and still saw an unparseable `hf_private` publish a public repo, #4367 is the follow-up that closed the parser gap.
</Note>

## Authentication

A write-scoped token, from an env var, a cached login, or config — any works.

```bash theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
export HF_TOKEN=hf_...
# or
huggingface-cli login
```

Or set it in `config.yaml` as `hf_token` — the config-level twin of the env var:

```yaml theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
# config.yaml
hf_token: "hf_xxx"
```

**Precedence:** `HF_TOKEN` env var wins, then a cached `huggingface-cli login`, then `hf_token` from config.

| Source       | Key                                   | When it wins            |
| ------------ | ------------------------------------- | ----------------------- |
| Env var      | `HF_TOKEN` / `HUGGING_FACE_HUB_TOKEN` | Always, if set          |
| Cached login | `huggingface-cli login`               | If no env var           |
| Config       | `hf_token`                            | If neither of the above |

The token must have **write** scope, and the repo must be under your own username or an org you can write to.

<Note>
  Prefer config-level `hf_token` inside CI configs where you don't want the token to leak into environment inspection. `hf_token` also reaches Unsloth as the download credential for **gated base models** (Llama, Gemma) — see [Unsloth Surface](/docs/features/praisonai-train-unsloth-surface#model-access).
</Note>

## Error translation

A rejected push turns into a one-line fix, not a stack trace — now shared by all three push sites (LLM, vision, and `upload-vision`) via `_hub.py::raise_hf_push_error`.

| Status | Message keyword              | What to do                                                                          |
| ------ | ---------------------------- | ----------------------------------------------------------------------------------- |
| 401    | "rejected the credentials"   | Run `huggingface-cli login`, or `export HF_TOKEN=…` with write scope                |
| 403    | "refused write access"       | Repo must be under your username / an org you can write to; token needs write scope |
| other  | "upload to '\<repo>' failed" | Raw upstream error preserved after the actionable prefix                            |

## Safety note on `hf_model_name`

Always use the namespaced form `me/model`, never a bare name.

`praisonai-train` deletes a **local** stale output directory of that name before an upload (`_hub.py::clean_local_repo_dir`), but a namespaced repo id like `me/model` is **never** treated as a path to delete — even if `./me/model` exists locally. A bare name with no `/` **is** treated as a local directory and removed.

<Warning>
  Setting `hf_model_name` to a bare directory name (no `/`) makes `praisonai-train` treat it as a **local** path and delete it before an export. Always prefer the namespaced form (`me/model`) so no local directory of that name can be wiped. This was a real defect in `upload_vision.py` before PR #4357.
</Warning>

## Best Practices

<AccordionGroup>
  <Accordion title="Leave hf_private unset for private repos">
    The default is private. Only add `hf_private: false` when you deliberately want a public repo — and double-check the dataset was public too.
  </Accordion>

  <Accordion title="Always namespace hf_model_name">
    Use `me/model`, never a bare `model`. A namespaced id is a Hub target and is never deleted as a local path.
  </Accordion>

  <Accordion title="Set a write token once">
    Run `huggingface-cli login` (cached tokens count) or `export HF_TOKEN=hf_...` with write scope before the run — [preflight](/docs/features/praisonai-train#preflight-validation) fails fast if it's missing.
  </Accordion>

  <Accordion title="Add commit_message and tags for traceability">
    `commit_message` and `tags` are only sent when set — use them to label each upload on the Hub.
  </Accordion>
</AccordionGroup>

## Related

<CardGroup cols={2}>
  <Card title="Export a trained model" icon="upload" href="/docs/features/praisonai-train-export">
    Publish an already-trained model to HF, GGUF, or Ollama without re-training.
  </Card>

  <Card title="Train" icon="graduation-cap" href="/docs/train">
    Full fine-tuning flow and config.yaml reference.
  </Card>

  <Card title="Preference Tuning" icon="scale-balanced" href="/docs/features/praisonai-train-preference-tuning">
    Fine-tune with DPO, ORPO, or KTO preference pairs.
  </Card>

  <Card title="Unsloth Surface" icon="sliders" href="/docs/features/praisonai-train-unsloth-surface">
    Gated model access, PEFT selectors, offline merge, and vLLM rollouts.
  </Card>
</CardGroup>
