Environment variables and state files
Soup reads a short list of environment variables and writes a handful of files outside the output directory of a run. This page lists them as of v0.75.2, with the rule each path override obeys and the command that creates each file. ~ is your home directory (%USERPROFILE% on Windows).
Every
soupinvocation appends one line to~/.soup/audit.jsonl,soup --helpincluded, unless audit logging is off. Running the CLI once is enough to create~/.soup/. To keep a scratch session out of your real home, setSOUP_NO_AUDIT_LOG=1and pointHOME(USERPROFILEon Windows) at a disposable directory.
Switches
| Variable | Accepted values | Effect |
|---|---|---|
SOUP_NO_AUDIT_LOG | 1, true, yes or on, in any case | Same as --no-audit-log: no line is appended to the audit log. Any other value, 0 included, leaves it on. |
SOUP_TELEMETRY | 1, true, yes or on, in any case | Opts in to telemetry, which is off by default. --no-telemetry is a root option and goes before the subcommand; it overrides this variable. As shipped, the bundled project key is a placeholder and nothing is sent even when you opt in. See Tracker and eval pro. |
SOUP_POSTHOG_KEY and SOUP_POSTHOG_ENDPOINT | A key of at most 256 characters with no control characters, and an HTTPS URL that passes the SSRF policy | Point telemetry at your own PostHog project. Set both. Only consulted when telemetry is opted in. |
Paths you can move
Each override below replaces one file or directory under ~/.soup/. They come in two kinds, and the difference matters when you mistype one.
- Contained overrides. The path is resolved, symlinks followed, and must sit under your home directory, the current working directory or the system temporary directory. Anything else is ignored and the default is used, with no error, so a path outside those three roots simply has no effect. Only
SOUP_AUDIT_LOG_PATHsays so, with a one-line warning on stderr (falling back to default); for the rest, check where the file actually appeared. Most of them also ignore a value that contains control characters (SOUP_BATCH_CACHE_PATHdoes not check, andSOUP_ADVISE_HISTORY_PATHrejects only a NUL byte). - Uncontained overrides.
SOUP_DB_PATH,SOUP_REGISTRY_DB_PATHandSOUP_DRAFT_REGISTRY_PATHare used exactly as given, with no containment check.
| Variable | Moves | Default | Kind |
|---|---|---|---|
SOUP_DB_PATH | The experiments database: every tracked run, soup runs, the eval leaderboard | ~/.soup/experiments.db | Uncontained |
SOUP_REGISTRY_DB_PATH | The model registry database | ~/.soup/registry.db | Uncontained |
SOUP_DRAFT_REGISTRY_PATH | The registry of distilled speculative-decoding drafts | ~/.soup/drafts.json | Uncontained |
SOUP_AUDIT_LOG_PATH | The audit log | ~/.soup/audit.jsonl | Contained, and at most 4096 characters |
SOUP_BATCH_CACHE_PATH | The cache of the batch size the OOM probe picked | ~/.soup/batch_cache.json | Contained |
SOUP_ADVISE_HISTORY_PATH | The soup advise verdict history | ~/.soup/advise_history.jsonl | Contained |
SOUP_DEPLOY_AUTOPILOT_CACHE | The soup deploy autopilot --measure cache | ~/.soup/deploy_autopilot_cache.json | Contained |
SOUP_EDIT_GOVERNOR_DB | The edit-governor store | ~/.soup/edit_governor.db | Contained, and at most 4096 characters |
SOUP_NAMESPACE_PIN_DB | The namespace-pin store | ~/.soup/namespace_pin.db | Contained, and at most 4096 characters |
SOUP_BRANCHES_DIR | The adapter-branch pointer directory, created if missing | ~/.soup/branches/ | Contained |
SOUP_LAYER_STREAM_CACHE_DIR | The layer-streaming shard cache root | ~/.soup/layer-stream/ | Contained, ~ expanded |
SOUP_SPECTRUM_CACHE_DIR | The Spectrum scan cache root, which also holds the weights copy described below | ~/.soup/spectrum/ | Contained, ~ expanded |
Variables Soup uses between its own processes
Neither of these is meant to be set by hand.
| Variable | Set by and read by | What it does |
|---|---|---|
SOUP_MCP_RUN_ID | Set by soup mcp serve --allow-execute on the training process it launches; read by soup train | soup train adopts it as its run id, so the experiments row and the MCP launch record describe the same run. |
SOUP_CANDIDATE_RUN_ID | Read by the pre-push hook that soup eval gate-install writes; you export it | The run the hook compares against the baseline. Unset, the hook prints SOUP_CANDIDATE_RUN_ID not set; skipping regression gate. and exits 0, so the push goes through ungated. See soup eval design. |
Behaviour hints
| Variable | Accepted values | Effect |
|---|---|---|
SOUP_BENCH_BACKEND | transformers, vllm, sglang or mlx, in any case | soup bench with --backend auto (the default) takes this before it inspects the model directory. An unrecognised value is ignored. |
SOUP_LOOP_TRACE_DIR | A directory | With --pre-wired, where soup loop harvests serve logs from. When unset it uses the served model's directory if that is a local directory, then .soup-loops/traces. It is deliberately not held to the working directory. See soup loop. |
SOUP_LOOP_SERVE_ENDPOINT | An http or https URL | With --pre-wired, the server soup loop activates a canary adapter on. Unset, nothing is deployed and the iteration says so. The host must be a loopback name, or a loopback, private or link-local IP literal; plain http is accepted only for loopback, so a private or link-local address needs https. A public host, or any hostname that is not a loopback name, is refused because Soup does not resolve DNS. |
SOUP_SIGNING_KEY | The path to an ed25519 private key in PEM form | The key for soup adapters sign --backend ed25519 and soup attest emit --sign ed25519 when --key is not given. It is a path, not the key text. |
Credentials and endpoints Soup reads
Soup reads these and stores none of them. The audit log masks the value of an option whose name contains token, key, secret, password or credential (a webhook URL does not match and is recorded as typed), and soup llama and the gh call behind --push are started with a filtered environment, as the table notes.
| Variable | Read by | Notes |
|---|---|---|
HF_TOKEN, HUGGINGFACE_HUB_TOKEN | Every Hugging Face operation: soup push, soup data push, soup deploy hf-space, downloads through Soup's hub wrapper | Order: an explicit token, HF_TOKEN, HUGGINGFACE_HUB_TOKEN, then the cached login at ~/.cache/huggingface/token and the legacy ~/.huggingface/token. See Hugging Face Hub integration. |
HF_ENDPOINT | The same operations | An alternative Hub endpoint. HTTPS for a remote host, plain HTTP only for loopback; 0.0.0.0 and any scheme other than http or https are refused. |
MODELSCOPE_ENDPOINT, MODELERS_ENDPOINT | --hub modelscope and --hub modelers | The same validation as HF_ENDPOINT. |
MODELSCOPE_API_TOKEN, MODELERS_TOKEN | Uploads to those two hubs | Each hub reads only its own credential and neither falls back to HF_TOKEN (since v0.75.1). |
OPENAI_API_KEY | soup data generate --provider openai; the judge client of soup eval judge | The judge client uses it only for the openai provider and never for server or ollama. With --provider openai --api-base <url> it is sent to the URL you name. In an eval-gate suite, an https judge gets it only when its host is exactly api.openai.com. |
ANTHROPIC_API_KEY | The Anthropic data provider and the Anthropic judge of the data-forge commands | Environment only. |
LANGFUSE_PUBLIC_KEY, LANGFUSE_SECRET_KEY | soup ingest --source langfuse --pull | Both required, environment only, never a flag, so they never reach the audit log. The other soup ingest sources do not fetch anything; for them the credential variable only changes a console note. See Trace ecosystem. |
LANGFUSE_BASE_URL, LANGFUSE_HOST | The same pull | The first one set wins, in that order. Default https://cloud.langfuse.com. It must be https://, and a private or loopback address also needs --allow-private-host. |
GITHUB_TOKEN, GH_TOKEN | soup ship --push and soup adapters pr --push | The first non-blank one, in that order, posts the PR comment through the gh program, which gets a filtered environment. |
LAMBDA_API_KEY, LAMBDA_SSH_KEY_NAME, LAMBDA_SSH_PRIVATE_KEY | soup train --cloud lambda --cloud-submit | All three are required. LAMBDA_REGION is optional and defaults to us-tx-1. See Backends. |
MODAL_TOKEN_ID, MODAL_TOKEN_SECRET | soup train --cloud modal --cloud-submit | Both set, or a ~/.modal.toml, or a prior modal setup. |
LLAMA_CPP_PATH | GGUF export | Resolution order: --llama-cpp, then this variable (ignored if the path does not exist), then ~/.soup/llama.cpp, then a fresh clone into ~/.soup/llama.cpp. |
LLAMA_CPP_HOME, GGML_CUDA, GGML_METAL, OMP_NUM_THREADS | soup llama | Passed through to the llama.cpp program, whose environment is otherwise filtered. Soup finds that program on PATH and does not read LLAMA_CPP_HOME itself, although its not-found message suggests setting it. |
ANTHROPIC_API_KEY, AZURE_API_BASE, AZURE_API_KEY, AZURE_API_VERSION, GEMINI_API_KEY, OPENAI_API_BASE, OPENAI_API_KEY, OPENROUTER_API_KEY | soup eval aider | Whichever of these are set are forwarded into the Docker container as --env NAME, so the value is never on the command line. |
CUDA_VERSION, CUDA_HOME | soup env lock | Either supplies the CUDA version it records. CUDA_HOME is parsed for a version in the path (.../cuda-12.1, .../v12.1); a path with no version supplies nothing. Failing that it reads the version from torch, but only if torch is already imported. It does not query nvidia-smi. |
Soup's own code never reads WANDB_API_KEY or MLFLOW_TRACKING_URI; the tracker libraries do.
Variables Soup sets
PYTORCH_CUDA_ALLOC_CONF=expandable_segments:True, for layer streaming on non-Windows systems, withsetdefaultsemantics and only if CUDA has not already been initialised. A value you set wins. Windows ignores it and Soup says so rather than claiming it took effect.NCCL_P2P_DISABLE=0andNCCL_IB_DISABLE=1, plusNCCL_NVLS_ENABLE=1on NVLink, withsetdefaultso your own values win. They are applied only by asoup train --gpus Nprocess that is already inside a launcher (for example one you started yourself withaccelerate launchand--gpus Nstill on the command line); the ranks thatsoup train --gpus Nlaunches for you do not receive--gpusand so do not set them.PYTHONIOENCODING=utf-8, on Windows at startup, so child processes inherit UTF-8 output.MASTER_ADDR=localhostandMASTER_PORT=29500, bysoup doctor --ncclfor the length of its bandwidth check; the previous values are restored afterwards.
Soup also reads, but does not set, the variables a launcher exports. RANK and WORLD_SIZE together, or any of ACCELERATE_MIXED_PRECISION, ACCELERATE_USE_DEEPSPEED and ACCELERATE_USE_FSDP, mark a process as an already-launched rank. RANK and LOCAL_RANK decide which process may write RL checkpoints. WORLD_SIZE is the first source for the world size a DeepSpeed config is resolved against, with the GPU count as the fallback, and LOCAL_WORLD_SIZE sets the ZeRO++ hierarchical-partition size when it divides that world size.
Variables that exist in the source and do nothing
API_HOST, API_PORT, API_KEY, GRADIO_HOST and GRADIO_PORT are parsed and validated by a helper (soup_cli.utils.ui_env.resolve_ui_env), but nothing in v0.75.2 calls that helper, so setting them changes nothing: soup ui --port 7899 with API_PORT, API_HOST and API_KEY all set still bound 127.0.0.1:7899 and printed a freshly generated token. Upstream's serving document lists them, which is why they are named here. The Web UI is configured with soup ui --host, --port and --auth-token; see Web UI.
Files under ~/.soup/
| Path | Created by | Notes |
|---|---|---|
experiments.db | Every tracked run: soup train, soup sweep, and the soup eval commands that save results (benchmark and custom always, judge and aider only when given --run-id). Commands that only read it, such as soup runs, create it empty | SOUP_DB_PATH moves it. See Experiment tracking. |
registry.db | Any command that opens the registry: soup registry, --attach-to-registry, soup card, soup can pack | SOUP_REGISTRY_DB_PATH moves it. Mode 0600 on POSIX. See Model registry. |
audit.jsonl | Every invocation | Past 100 MiB the writer rotates it to audit.jsonl.1, keeping one backup. SOUP_AUDIT_LOG_PATH moves it; soup audit-log tail and soup audit-log rotate read and rotate it. See Governance. |
advise_history.jsonl | soup advise run --record | SOUP_ADVISE_HISTORY_PATH moves it. |
advise_last.json | soup advise run | Scratch for soup advise explain. No override. |
datasets.json | soup data register | The registry that soup data registry lists. No override. |
batch_cache.json | An SFT run that uses the OOM-probe batch size | SOUP_BATCH_CACHE_PATH moves it. |
deploy_autopilot_cache.json | soup deploy autopilot --measure | SOUP_DEPLOY_AUTOPILOT_CACHE moves it. |
drafts.json | soup draft distill | Created on first registration. SOUP_DRAFT_REGISTRY_PATH moves it. See soup draft. |
edit_governor.db | soup edit set, unless --no-governor | SOUP_EDIT_GOVERNOR_DB moves it. |
namespace_pin.db | A Hugging Face download through Soup's hub wrapper | SOUP_NAMESPACE_PIN_DB moves it. See Supply chain security. |
branches/ | soup adapters branch | One <name>.json pointer per branch. SOUP_BRANCHES_DIR moves it. |
telemetry_id | The first opted-in telemetry event | A random UUID, created even though, as shipped, nothing is sent. Delete it and a new one is generated on the next opt-in. |
llama.cpp/ | The first GGUF export that finds no llama.cpp | A clone. Skipped when --llama-cpp or LLAMA_CPP_PATH supplies one. |
layer-stream/<model>/ | A layer-streaming run | One shard per decoder layer, keyed to the source weights. SOUP_LAYER_STREAM_CACHE_DIR moves the root; the pre-flight checks free space on the volume before it writes. See Layer streaming. |
spectrum/<model>.json | soup spectrum scan | The scan result. --no-cache skips it. SOUP_SPECTRUM_CACHE_DIR moves the root. |
spectrum/weights/<model>/ | soup spectrum scan and layer streaming, for a Hugging Face model | A regular-file copy of the model's weights, made only when the Hub snapshot's files are symlinks that the sharder will not follow. It is as large as the weights; SOUP_SPECTRUM_CACHE_DIR moves it. |
sae-cache/<repo>/ | soup probe sae-diff --auto-download | No override. |
Files in the working directory
| Path | Created by | Notes |
|---|---|---|
.soup/loop.yaml and .soup-loops/ | soup loop | The loop's state file, and below .soup-loops/ its pairs/, adapters/, traces/ and one <iteration-id>/iteration.json per iteration. All held to the working directory. |
.soup/mcp-runs/ | soup mcp serve --allow-execute | A <run_id>.log per executed run, and the config snapshot taken at plan time under <run_id>/. Relative to the server's working directory. |
.soup-crashes/crash_<UTC>_<hex>.crash | A soup train run that fails with an exception | Written once the failure is recorded. It holds the error trace, the run's config and metrics, GPU state and an environment summary that names fourteen non-secret variables (among them CUDA_VISIBLE_DEVICES, PYTORCH_CUDA_ALLOC_CONF, HF_ENDPOINT, HF_HOME, WORLD_SIZE and RANK), with token-shaped strings redacted. Read it before you attach it to a public issue. |
.soup_hub_cache/ | A model fetched from ModelScope or Modelers (training.hub in soup.yaml, or --hub on a command that takes one), and Modelers datasets from soup data download --hub modelers | Hugging Face downloads do not use it. Must stay under the working directory. |
soup-env.lock | soup env lock | The default name; --output changes it. |
soup.tfstate | soup plan and soup apply | The default name; --state changes it. |
.soup-signature.json | soup adapters sign | Inside the adapter directory. |
.checkpoint_now | Nothing | Not a working trigger at v0.75.2: no code in soup train polls it, so touching it does nothing. See Observability. |
grace_codebook.json | soup edit set --method grace | A sidecar in the edit's output directory. |
.soup_build_state.sqlite | soup build | Under the build's output directory. |
Soup also creates short-lived temporaries in the directory it is working in, named .soup_merge_tmp_<name>, .soup_gguf_*, .soup.*.tmp and .soup-diskprobe-* (the last is the 64 MiB probe file of soup doctor --disk). They are scratch files, not state.
See also
- Configuration, for what belongs in
soup.yamlrather than the environment. - CLI reference, including the root options
--no-audit-log,--no-telemetryand--log-level. - Supply chain security and Governance, for what the audit log, the pin store and the signing key are for.
Soup is free and Apache-2.0. If it saved you a training run, starring the repo costs nothing and helps most. You can also fund the GPU time behind the work a 4 GB laptop cannot reach.