Skip to main content
A StarForge lab is a normal git repository on your machine. The console never clones it. sf submit packs a subset of files, uploads that bundle, and the server injects the Job Capsule on top.

After sf init my-lab --yes

starforge.yaml currently needs a name whose characters match [A-Za-z0-9._-]. That name is the console project. Do not pass --project on submit.
Commands that need a project (sf new, submit, ls, validate) walk up from the current directory looking for this file. CI can set SF_REPO_ROOT instead of cd. sf login / logout / status are global and do not need it.

One experiment directory

custom/custom also gets train.sh (the only entrypoint). You can add train.py next to it. Plugins add plugins.lock.json after sf plugin install … --exp. Do not put a framework file in the experiment and expect the platform to notice. The lock file is the method.

What gets uploaded

The CLI packs the experiment, common/, and configs/. The same exclude list is shared with the server (PACKAGE_EXCLUDES in starforge.contract.env): The JobSpec lands in the bundle at .starforge/jobspec.json. That path is inside .starforge/, not .forge/. Mixing the two directories is a real footgun: .forge is excluded, so a spec written there never reaches the cluster.

What does not live in the lab

  • Cluster kubeconfig, Slurm JWT, object-storage keys
  • The Job Capsule (runner.pex). The server injects it after admit.
  • Hardware parallelism. That comes from --profile and the registry.

Git

Submit records NRL_GIT_COMMIT and NRL_GIT_DIRTY. A dirty tree is rejected unless you pass --allow-dirty. Untracked files are listed as warnings either way. Initialize git at sf init (the default) so the first commit is not an afterthought.