# Run your own code

> Run a training script from your own directory on a GPU with nodus run, follow it, download its output and read what it cost.

Source: https://www.nodus-compute.ai/docs/getting-started/quickstart/
Build revision: 53bfc045e800bf7bb44fa18623013c7aa9c9971e

This page runs a script from your own directory on a GPU, then downloads the file it wrote. It assumes you have [installed the CLI and signed in](https://www.nodus-compute.ai/docs/getting-started/install/). The source and command sequence live in the repository’s `examples/cli/quickstart` example. Creating an organization requires [email and card verification](https://www.nodus-compute.ai/docs/getting-started/install/#creating-your-first-organization).

1. **Put your code in a directory.** Any directory works; this one holds a small PyTorch training loop that saves its final metrics to `/nodus/outputs/metrics.json`.

   train.py

   ```python
   """Fit a small linear model, print progress and save metrics.json as the declared output "metrics"."""

   import json
   import pathlib

   import torch

   device = "cuda" if torch.cuda.is_available() else "cpu"
   print("device:", torch.cuda.get_device_name() if device == "cuda" else "cpu")

   torch.manual_seed(0)
   x = torch.randn(1024, 16, device=device)
   y = x @ torch.randn(16, 1, device=device)
   w = torch.zeros(16, 1, device=device, requires_grad=True)
   opt = torch.optim.SGD([w], lr=0.1)

   for step in range(200):
       loss = ((x @ w - y) ** 2).mean()
       opt.zero_grad()
       loss.backward()
       opt.step()
       if step % 50 == 0:
           print(f"step {step} loss {loss.item():.4f}")

   print(f"final loss {loss.item():.6f}")
   out = pathlib.Path("/nodus/outputs")
   out.mkdir(parents=True, exist_ok=True)
   (out / "metrics.json").write_text(json.dumps({"final_loss": loss.item(), "steps": 200}))
   ```

2. **Review the estimate, then run.** From the directory containing `train.py`:

   Terminal window

   ```sh
   nodus run --name cli-quickstart --gpu L4 --image nodus/pytorch \
     --max-cost 1 --timeout 10m --no-warm --dry-run \
     --output metrics=/nodus/outputs/metrics.json -- python train.py
   ```

   This dry run uploads the directory for inspection but does not create the Job. Inspect the estimate and any blockers. The limits are choices for this example, not a price quote or a guarantee that it will complete. After you accept the estimate, submit the same request without `--dry-run`:

   Terminal window

   ```sh
   nodus run --name cli-quickstart --gpu L4 --image nodus/pytorch \
     --max-cost 1 --timeout 10m --no-warm \
     --output metrics=/nodus/outputs/metrics.json -- python train.py
   ```

   This starts paid compute. The CLI uploads this directory, streams the logs and returns your command’s exit code. Check for a successful final status and training progress in the logs. The script runs 200 steps and writes `metrics.json`; its exact loss and runtime depend on the environment. Files excluded by `.gitignore` or `.nodusignore` stay local. Inspect the directory before uploading it.

3. **Get the output.** The `--output` flag declared `metrics`; copy it back:

   Terminal window

   ```sh
   nodus cp job/cli-quickstart:outputs/metrics metrics.json
   ```

   The file is checked against its SHA-256 digest. Inspect `final_loss` and `steps` in the downloaded JSON. If the Job fails or no output is listed, inspect its status and logs instead of reporting a saved result.

## Leave it running

Press **Ctrl+C** during a run and the CLI asks whether to cancel the Job; answer `n` to detach and leave it running. Or start with `-d` to return as soon as the Job exists. A detached Job keeps running:

Terminal window

```sh
nodus get jobs                        # every Job in the project, with phase and cost so far
nodus get jobs --mine -w              # only yours, updating live
nodus logs -f job/cli-quickstart      # stream the output again
nodus describe job/cli-quickstart     # attempts, placement, cost, conditions and events
nodus cancel job/cli-quickstart       # request cancellation, then verify status
```

## Control the cost

|Flag|Effect|
|-|-|
|`--max-cost 5`|Set a $5 Job spending limit; choose a limit that fits your Job|
|`--timeout 2h`|The Job is stopped after two hours of wall-clock time|
|`--dry-run`|Review the estimate without creating the Job|

`nodus billing` shows your balance and this month’s spend; `nodus billing usage --group-by day` breaks it down.

Exit codes

`nodus run` exits with your command’s own exit code. It exits `125` when Nodus could not run the command (an API error or an invalid request), `124` on `--timeout` and `130` when you interrupt it.

## Clean up

Finished Jobs are kept for 30 days so you can read their logs and outputs, then deleted. To delete one now:

Terminal window

```sh
nodus delete job/cli-quickstart
```

## Next steps

* [Nodus for kubectl users](https://www.nodus-compute.ai/docs/getting-started/kubectl-users/): manifests, `apply`, `get -o`, `wait` and `diff`.
* [CLI reference](https://www.nodus-compute.ai/docs/reference/cli/): every command and flag, with tested examples.
