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 soup invocation appends one line to ~/.soup/audit.jsonl, soup --help included, unless audit logging is off. Running the CLI once is enough to create ~/.soup/. To keep a scratch session out of your real home, set SOUP_NO_AUDIT_LOG=1 and point HOME (USERPROFILE on Windows) at a disposable directory.

Switches

VariableAccepted valuesEffect
SOUP_NO_AUDIT_LOG1, true, yes or on, in any caseSame as --no-audit-log: no line is appended to the audit log. Any other value, 0 included, leaves it on.
SOUP_TELEMETRY1, true, yes or on, in any caseOpts 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_ENDPOINTA key of at most 256 characters with no control characters, and an HTTPS URL that passes the SSRF policyPoint 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_PATH says 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_PATH does not check, and SOUP_ADVISE_HISTORY_PATH rejects only a NUL byte).
  • Uncontained overrides. SOUP_DB_PATH, SOUP_REGISTRY_DB_PATH and SOUP_DRAFT_REGISTRY_PATH are used exactly as given, with no containment check.
VariableMovesDefaultKind
SOUP_DB_PATHThe experiments database: every tracked run, soup runs, the eval leaderboard~/.soup/experiments.dbUncontained
SOUP_REGISTRY_DB_PATHThe model registry database~/.soup/registry.dbUncontained
SOUP_DRAFT_REGISTRY_PATHThe registry of distilled speculative-decoding drafts~/.soup/drafts.jsonUncontained
SOUP_AUDIT_LOG_PATHThe audit log~/.soup/audit.jsonlContained, and at most 4096 characters
SOUP_BATCH_CACHE_PATHThe cache of the batch size the OOM probe picked~/.soup/batch_cache.jsonContained
SOUP_ADVISE_HISTORY_PATHThe soup advise verdict history~/.soup/advise_history.jsonlContained
SOUP_DEPLOY_AUTOPILOT_CACHEThe soup deploy autopilot --measure cache~/.soup/deploy_autopilot_cache.jsonContained
SOUP_EDIT_GOVERNOR_DBThe edit-governor store~/.soup/edit_governor.dbContained, and at most 4096 characters
SOUP_NAMESPACE_PIN_DBThe namespace-pin store~/.soup/namespace_pin.dbContained, and at most 4096 characters
SOUP_BRANCHES_DIRThe adapter-branch pointer directory, created if missing~/.soup/branches/Contained
SOUP_LAYER_STREAM_CACHE_DIRThe layer-streaming shard cache root~/.soup/layer-stream/Contained, ~ expanded
SOUP_SPECTRUM_CACHE_DIRThe 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.

VariableSet by and read byWhat it does
SOUP_MCP_RUN_IDSet by soup mcp serve --allow-execute on the training process it launches; read by soup trainsoup train adopts it as its run id, so the experiments row and the MCP launch record describe the same run.
SOUP_CANDIDATE_RUN_IDRead by the pre-push hook that soup eval gate-install writes; you export itThe 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

VariableAccepted valuesEffect
SOUP_BENCH_BACKENDtransformers, vllm, sglang or mlx, in any casesoup bench with --backend auto (the default) takes this before it inspects the model directory. An unrecognised value is ignored.
SOUP_LOOP_TRACE_DIRA directoryWith --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_ENDPOINTAn http or https URLWith --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_KEYThe path to an ed25519 private key in PEM formThe 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.

VariableRead byNotes
HF_TOKEN, HUGGINGFACE_HUB_TOKENEvery Hugging Face operation: soup push, soup data push, soup deploy hf-space, downloads through Soup's hub wrapperOrder: 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_ENDPOINTThe same operationsAn 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 modelersThe same validation as HF_ENDPOINT.
MODELSCOPE_API_TOKEN, MODELERS_TOKENUploads to those two hubsEach hub reads only its own credential and neither falls back to HF_TOKEN (since v0.75.1).
OPENAI_API_KEYsoup data generate --provider openai; the judge client of soup eval judgeThe 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_KEYThe Anthropic data provider and the Anthropic judge of the data-forge commandsEnvironment only.
LANGFUSE_PUBLIC_KEY, LANGFUSE_SECRET_KEYsoup ingest --source langfuse --pullBoth 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_HOSTThe same pullThe 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_TOKENsoup ship --push and soup adapters pr --pushThe 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_KEYsoup train --cloud lambda --cloud-submitAll three are required. LAMBDA_REGION is optional and defaults to us-tx-1. See Backends.
MODAL_TOKEN_ID, MODAL_TOKEN_SECRETsoup train --cloud modal --cloud-submitBoth set, or a ~/.modal.toml, or a prior modal setup.
LLAMA_CPP_PATHGGUF exportResolution 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_THREADSsoup llamaPassed 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_KEYsoup eval aiderWhichever 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_HOMEsoup env lockEither 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, with setdefault semantics 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=0 and NCCL_IB_DISABLE=1, plus NCCL_NVLS_ENABLE=1 on NVLink, with setdefault so your own values win. They are applied only by a soup train --gpus N process that is already inside a launcher (for example one you started yourself with accelerate launch and --gpus N still on the command line); the ranks that soup train --gpus N launches for you do not receive --gpus and so do not set them.
  • PYTHONIOENCODING=utf-8, on Windows at startup, so child processes inherit UTF-8 output.
  • MASTER_ADDR=localhost and MASTER_PORT=29500, by soup doctor --nccl for 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/

PathCreated byNotes
experiments.dbEvery 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 emptySOUP_DB_PATH moves it. See Experiment tracking.
registry.dbAny command that opens the registry: soup registry, --attach-to-registry, soup card, soup can packSOUP_REGISTRY_DB_PATH moves it. Mode 0600 on POSIX. See Model registry.
audit.jsonlEvery invocationPast 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.jsonlsoup advise run --recordSOUP_ADVISE_HISTORY_PATH moves it.
advise_last.jsonsoup advise runScratch for soup advise explain. No override.
datasets.jsonsoup data registerThe registry that soup data registry lists. No override.
batch_cache.jsonAn SFT run that uses the OOM-probe batch sizeSOUP_BATCH_CACHE_PATH moves it.
deploy_autopilot_cache.jsonsoup deploy autopilot --measureSOUP_DEPLOY_AUTOPILOT_CACHE moves it.
drafts.jsonsoup draft distillCreated on first registration. SOUP_DRAFT_REGISTRY_PATH moves it. See soup draft.
edit_governor.dbsoup edit set, unless --no-governorSOUP_EDIT_GOVERNOR_DB moves it.
namespace_pin.dbA Hugging Face download through Soup's hub wrapperSOUP_NAMESPACE_PIN_DB moves it. See Supply chain security.
branches/soup adapters branchOne <name>.json pointer per branch. SOUP_BRANCHES_DIR moves it.
telemetry_idThe first opted-in telemetry eventA 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.cppA clone. Skipped when --llama-cpp or LLAMA_CPP_PATH supplies one.
layer-stream/<model>/A layer-streaming runOne 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>.jsonsoup spectrum scanThe 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 modelA 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-downloadNo override.

Files in the working directory

PathCreated byNotes
.soup/loop.yaml and .soup-loops/soup loopThe 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-executeA <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>.crashA soup train run that fails with an exceptionWritten 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 modelersHugging Face downloads do not use it. Must stay under the working directory.
soup-env.locksoup env lockThe default name; --output changes it.
soup.tfstatesoup plan and soup applyThe default name; --state changes it.
.soup-signature.jsonsoup adapters signInside the adapter directory.
.checkpoint_nowNothingNot a working trigger at v0.75.2: no code in soup train polls it, so touching it does nothing. See Observability.
grace_codebook.jsonsoup edit set --method graceA sidecar in the edit's output directory.
.soup_build_state.sqlitesoup buildUnder 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

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.