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

# Create and tune an experiment

> What tp init and tp new put on disk, how config inheritance works, and how to validate before you queue.

```bash theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
tp new my-grpo --method nemo-rl/grpo
```

Creates `experiments/my-grpo/` with a config inherited from the method's template, a README of
tuning notes, and a lock file pinning the method version. No GPUs are involved yet.

## Before you start

Run it inside a project. `tp init my-lab --yes` makes one, and every command that needs a
project walks up from the current directory looking for `tuneplane.yaml`.

```text theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
my-lab/
├── tuneplane.yaml      # the marker `tp` finds the project root by, and the project name
├── experiments/        # tp new writes here
├── configs/
│   ├── base/           # the official method bases
│   └── models/         # model fragments
├── common/             # shared code: data scripts, environments, reward functions
├── .gitignore
└── README.md
```

The `name` in `tuneplane.yaml` is the project the console groups your jobs under. Characters
are limited to `[A-Za-z0-9._-]`. Do not pass `--project` on submit; it comes from here.

In CI, set `TUNEPLANE_CLIENT_REPO_ROOT` instead of changing directory. `tp login`, `tp logout`
and `tp status` are global and need no project.

## What one experiment holds

```text theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
experiments/my-grpo/
├── config.yaml           # your diffs, inherited through `defaults`
├── README.md             # scaffold notes, never executed
└── recipe.lock.json      # the method and framework version pin
```

A `custom/custom` experiment also gets `train.sh`, which is its only entrypoint. You can put a
`train.py` beside it. `tp plugin install … --exp` adds `plugins.lock.json`.

The lock file **is** the method. Adding a `framework` file to the directory does nothing.

## Write only the diff

An experiment inherits from the official bases and holds what you changed:

```yaml experiments/my-grpo/config.yaml theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
defaults:
  - ../../configs/base/grpo_math_1B.yaml     # the official base
  - ../../configs/models/qwen3.5-9b.yaml     # a model fragment

policy:
  optimizer:
    kwargs:
      lr: 2.0e-6

grpo:
  num_generations_per_prompt: 8

loss_fn:
  reference_policy_kl_penalty: 0.01
```

Parallelism, GPU memory tuning and NCCL settings are **not** in this file. They arrive from the
server's hardware registry when you pass `--profile`, so the same experiment runs on a
different GPU type without an edit. See [config.yaml](https://docs.tuneplane.ai/en/guides/config.md) for how the layering
resolves.

The top of the scaffold carries a comment block listing the keys people change most, with
useful ranges.

## Start from an experiment that already works

```bash theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
tp new my-grpo-v2 --from my-grpo
```

Copies the source experiment's config and its lock. `--method` is ignored, because the lock
comes with it.

## Validate before you queue

```bash theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
tp validate my-grpo
```

Checks four things against the method declaration:

| Check | What fails |
| - | - |
| Key names | A misspelled key. The config is validated in struct mode, so unknown keys are errors |
| Types and ranges | A learning rate or batch size outside the declared range |
| Batch relationships | GRPO checks rollout batch against train batch. Not divisible is an error; divisible but unequal is an off-policy warning |
| Required data | A missing `--model` or `--train-data` for verl and TRL |

`tp submit` runs the same validation. `--no-validate` skips it, which mostly buys you a queue
wait before the same error.

## Browse what you can tune

```bash theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
tp methods                # every method, with the framework versions it supports
tp methods nemo-rl/grpo   # this method's parameters: type, default, range, description
tp ls                     # the experiments in this project
```

The console's [Methods page](https://docs.tuneplane.ai/en/console/methods.md) is the same catalogue with a search box.

## What else can live in an experiment directory

| File | Purpose |
| - | - |
| `train.sh` | Custom jobs only: the entrypoint. See [custom training](https://docs.tuneplane.ai/en/guides/custom-training.md) |
| Environment or reward modules | Put them in `common/` and reference them from the config. They travel with the job package |
| `plugins.lock.json` | Written by `tp plugin install --exp`. The platform resolves it at submission |

## Check it worked

`tp validate my-grpo` prints no errors, and `experiments/my-grpo/recipe.lock.json` names the
method you asked for. Then [submit it](https://docs.tuneplane.ai/en/guides/submit.md).

## Next

[config.yaml inheritance](https://docs.tuneplane.ai/en/guides/config.md) · [Submitting a job](https://docs.tuneplane.ai/en/guides/submit.md) ·
[Sweeps](https://docs.tuneplane.ai/en/guides/sweep.md)

> **Why git matters here**
>
> `tp submit` records the commit, and refuses a dirty tree unless you pass `--allow-dirty`.
> That is what lets you read a result six months later and know which code produced it.
>
> Git is not required to submit. Without a repository the run is recorded with no commit, and
> the file list changes: instead of git applying `.gitignore`, the bundle is walked against the
> platform's built-in exclusions and refused above 64 MB, so a checkpoint directory cannot
> quietly become an upload. Raise that ceiling with `TUNEPLANE_CLIENT_MAX_PACKAGE_MB` if a
> project genuinely needs to ship something large.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.