Buckets:
HF Jobs Development: operator and agent guide
This extension turns a Hugging Face Job into a remote GPU execution target while keeping the editor and source tree
local. Use the Code OSS commands for the interactive workflow and the hf-dev CLI primitives for automation.
Mental model
local Git checkout (authoritative)
|
| Mutagen one-way replica / sync-file
v
HF Job:/workspace/hf-dev/<repo-key>-<repo-name>
|
| editable install of the synchronized checkout
v
remote Python + CUDA
|
| debugpy over an SSH local port forward
v
local Code OSS debugger and local breakpoints
The local checkout is always authoritative. Do not make source changes only on the Job: Mutagen runs in
one-way-replica mode and can overwrite or remove remote-only changes. Edit locally, save, and let the extension sync.
Requirements
hf >= 1.28.0, authenticated withhf auth login.- A token allowed to create/use Jobs and read the required Hub models. Bucket permissions are required only when the optional persistent cache is explicitly enabled.
- An SSH public key registered at https://huggingface.co/settings/keys.
ssh,scp, and Mutagen installed locally. A Homebrew Mutagen installation is supported on macOS.hf-devinstalled onPATH, normally at~/.local/bin/hf-dev.- The Code OSS Python and debugpy extensions for F5 debugging.
Check the local prerequisites without starting paid compute:
hf auth whoami
hf-dev doctor --repo "$PWD"
hf-dev plan --repo "$PWD" --flavor h200 --timeout 30m
plan prints the exact hf jobs run command but does not create a Job.
Normal Code OSS workflow
- Open the local repository in Code OSS.
- Run HF Dev: Start or Reconnect GPU Job from the command palette or click the HF Dev status item.
- Select hardware and one of the hard limits:
30m,1h, or8h. - Edit and save files locally. Save events synchronize the file to the active Job.
- Open the Python entry point and press F5. On macOS, use
fn/Globe + F5 unless the function row is configured as standard F-keys. F5 reveals the HF Dev Output channel without moving editor focus; remote stdout, stderr, and Hub progress are streamed there rather than tohf jobs logs. - Run HF Dev: Stop GPU Job as soon as the GPU is no longer needed.
F5 is intercepted only for a Python editor when hfDev.active is true and no debug session is already active. During
an attached debug session, F5 keeps its normal Continue behavior. Without an active HF development Job, local F5 is
unchanged. HF Dev permits only one remote debugger per workspace: ending the local attach stops the matching remote
process, and a newer debug launch replaces an older process left by a disconnected editor.
What hf-dev up does
For a newly created Job, hf-dev up performs these operations in order:
- Resolve configuration and verify the current
hfCLI version. - If and only if
cache_bucketis explicitly configured, create or reuse that private Bucket and include it as a read-writeHF_HOMEmount. The default MVP creates and mounts no Bucket. - Submit an SSH-enabled detached Job with the chosen image, flavor, and native Hub timeout. Without the opt-in mount, Hugging Face libraries use the image's ephemeral Job-local cache.
- Start a detached local watchdog. At the same hard deadline it checks the Job and sends
hf jobs cancelif the Job remains active. It retries after temporary network loss. The native Hub timeout remains a second guard. - Wait until SSH accepts connections.
- Discover a usable remote Python interpreter (
python3,python, common absolute paths, or an explicit setting). - Install the matching Mutagen agent through SSH and create a one-way replica of the local repository.
- Bootstrap the remote environment. The default installs
debugpyand installs the synchronized repository editable, preferringuv pip install -e .and falling back topython -m pip install -e .. - Import
transformersand verify that it resolves to<remote_root>/src/transformers, not the image's preinstalled site-packages copy.
If setup of a newly created Job fails, hf-dev terminates its Mutagen session and attempts to cancel the Job
immediately.
CLI primitives for people and agents
All repository-scoped commands accept --repo PATH; when omitted, hf-dev resolves the current Git root.
Inspect without changing state
# Local recorded state only. Fast, but it can be stale after cancellation in the Hub UI.
hf-dev info --repo "$PWD"
# Local state plus authoritative remote Job status.
hf-dev info --repo "$PWD" --remote
# Authoritative Job details for the recorded Job.
hf-dev status --repo "$PWD"
# Check tools and versions without contacting Jobs.
hf-dev doctor --repo "$PWD"
# Preview a launch without starting paid compute.
hf-dev plan --repo "$PWD" --flavor h200 --timeout 30m
Agents should use info --remote or status before assuming paid compute is active. Plain info reports whether a
local state record exists; it deliberately avoids a Hub request.
Start or reconnect
hf-dev up --repo "$PWD" --flavor h200 --timeout 30m
If the recorded Job is active, up reconnects, recreates synchronization, and revalidates the environment. If it is
terminal, up creates a new Job. Always choose an explicit flavor and timeout in automation so cost is visible in the
invocation.
Useful launch overrides:
hf-dev up --repo "$PWD" --flavor h200 --timeout 1h --cache-bucket my-org/shared-dev-cache
hf-dev up --repo "$PWD" --flavor h200 --timeout 1h --no-cache # override a TOML cache setting
hf-dev up --repo "$PWD" --flavor h200 --timeout 1h --image my-image:tag
Synchronize local source
# Flush the Mutagen replica; recreate the session automatically if it is unhealthy.
hf-dev sync --repo "$PWD"
# Synchronize one file. The path must be inside the repository.
hf-dev sync-file --repo "$PWD" path/to/file.py
Mutagen ignores VCS data, virtual environments, Python caches, test/type/lint caches, build outputs, and
node_modules. The extension serializes save-triggered sync operations per workspace. A transient Mutagen flush is
retried and an unavailable session is recreated automatically.
Run commands and open a shell
# Run from the synchronized remote repository root.
hf-dev run --repo "$PWD" 'nvidia-smi'
hf-dev run --repo "$PWD" 'python -m pytest tests/models/foo/test_modeling_foo.py -q'
# Open an interactive login shell already positioned at the remote repository root.
hf-dev shell --repo "$PWD"
Quote a compound remote command as one argument. Do not insert a standalone -- after the run options; it would be
passed to the remote shell as part of the command.
hf-dev run is preferable to raw SSH for automation because it resolves the recorded Job, validates that it is active,
and changes to remote_root first.
Use raw Job SSH
The JSON from hf-dev info --remote contains namespace, job_id, and remote_root. Given those values:
hf jobs ssh NAMESPACE/JOB_ID
The equivalent direct OpenSSH form is:
ssh JOB_ID@ssh.hf.jobs
Raw SSH starts outside the repository. Change to the remote_root reported by hf-dev info before running project
commands. Raw SSH is useful for an agent that needs an interactive TTY or a tool not wrapped by hf-dev; use
hf-dev run for ordinary non-interactive commands.
Debug manually
Code OSS normally owns the attach sequence. The lower-level primitive is:
hf-dev debug --repo "$PWD" --port 5678 path/to/script.py arg1 arg2
hf-dev debug --repo "$PWD" --port 5678 --module pytest tests/path/test_file.py -k test_name
hf-dev debug-stop --repo "$PWD"
The command flushes source, verifies the editable import, opens an SSH local forward, starts remote debugpy, prints
HF_DEV_DEBUG_READY, and waits for a client. Attach a local debugpy client to 127.0.0.1:5678 with this mapping:
localRoot = local repository root
remoteRoot = remote_root from hf-dev info
The extension obtains a free local port, starts this primitive, waits for the readiness marker, and invokes the Code
OSS debugger with justMyCode: false. Breakpoints must be placed in local files; path mapping associates them with the
synchronized remote files. Each debug invocation records a verified remote PID under /tmp; a new invocation stops
the previous debugger for that workspace before starting. debug-stop removes any current or legacy HF Dev debugpy
process whose working directory is the synchronized workspace. Debug stdout and stderr travel over SSH into the
extension's HF Dev Output channel; they are not emitted by the Job's sleep infinity container command and
therefore do not appear in hf jobs logs.
Logs and shutdown
hf-dev logs --repo "$PWD"
hf-dev logs --repo "$PWD" --follow
# Terminates Mutagen, sends hf jobs cancel, and removes local state after success.
hf-dev down --repo "$PWD"
After work, verify that no development Job remains active:
hf jobs list --status RUNNING --label hf-dev=true
Cancellation through the Hub UI is valid, but local state remains until the next lifecycle action. Use
info --remote to distinguish stale local state from a running Job.
How the extension maps to CLI primitives
- Start or Reconnect GPU Job ->
hf-dev up --flavor ... --timeout ... - Sync Workspace Now ->
hf-dev sync - save event ->
hf-dev sync-file <saved-file> - Open Remote Shell ->
hf-dev shell - Run Remote Command ->
hf-dev run '<command>' - Debug Current Python File / F5 -> save,
sync-file,hf-dev debug <relative-file>, debugpy attach - Debug Current File with Pytest -> save,
sync-file,hf-dev debug --module pytest <relative-file> - Follow Job Logs ->
hf-dev logs --follow - Stop GPU Job ->
hf-dev down
The extension is intentionally a thin UI. Agents can use the same lifecycle entirely through hf-dev without Code
OSS.
State, identity, and cache
Local state is stored per repository root under:
~/.local/state/hf-dev/<repo-key>.json
Important fields include job_id, namespace, remote_root, python, mutagen_session, timeout,
cancel_deadline, cancel_watchdog_pid, cache_bucket, and cache_home.
The default Job name and Mutagen session contain a stable hash of the absolute local repository root. Consequently, two clones in different local paths get separate state and remote workspaces.
The default uses the image's Job-local Hugging Face cache and creates no Bucket. Downloads are reused by later debug runs within the same Job, then discarded when that Job ends. Every new Job starts cold.
Persistent caching is an explicit --cache-bucket OWNER/NAME or TOML opt-in. It mounts the Bucket read-write at
/cache/huggingface, sets it as HF_HOME, and disables symlinks. This avoids downloading the same revision again, but
large safetensors files are then read through the remote FUSE mount and can load more slowly than Xet into local Job
storage. Avoid concurrent writers and do not treat this optional mode as the MVP path.
The user's token is forwarded by secret name (--secrets HF_TOKEN), not embedded in the Job command. Do not print,
copy, or place token values in configuration or command arguments.
Configuration
Configuration precedence, from lowest to highest, is built-in defaults, user TOML, repository TOML, and CLI options.
User configuration:
~/.config/hf-dev/config.toml
Repository configuration:
<repo>/.hf-dev.toml
Example:
[hf-dev]
image = "huggingface/transformers-all-latest-gpu"
flavor = "h200"
timeout = "1h"
python = "auto"
cache_bucket = false # default; optionally set an explicit private OWNER/NAME Bucket
forward_hf_token = true
# namespace = "my-org"
# resource_group_id = "..."
# identity_file = "~/.ssh/id_ed25519"
# bootstrap = "{python} -m pip install -q debugpy && {python} -m pip install -e ."
Code OSS settings:
hfDev.command: launcher path; defaults tohf-devand searches common user/Homebrew locations.hfDev.syncOnSave: automatically synchronize saved files; defaults totrue.hfDev.defaultFlavor: initially selected hardware.hfDev.defaultTimeout: initially selected hard timeout (30m,1h, or8h).
Useful environment overrides are HF_DEV_HF_BIN, HF_DEV_MUTAGEN_BIN, HF_DEV_SSH_BIN, HF_DEV_SCP_BIN,
HF_DEV_MUTAGEN_AGENTS, HF_DEV_CONFIG, and HF_DEV_STATE_DIR.
Safety rules for agents
- Never start a paid Job merely to inspect configuration; use
doctor,plan, and local source inspection. - Make the hardware flavor and timeout explicit before starting a Job.
- Use the shortest practical timeout. The extension offers
30m,1h, and8h. - Treat the local checkout as authoritative and never depend on remote-only source files.
- Expect model downloads to disappear with the Job. Persist checkpoints and other required outputs explicitly to a user-chosen Hub repository or Bucket.
- On setup failure, verify cancellation. On normal completion, run
hf-dev downand verify no labeled Job remains. - The local watchdog supplements the Hub timeout but needs the local machine to reconnect after prolonged offline time.
- Do not manipulate another user's Job or Bucket unless explicitly authorized.
- This release targets single-node Jobs. Multi-node orchestration is not implemented yet.
Troubleshooting
spawn hf-dev ENOENT: install the launcher at~/.local/bin/hf-devor sethfDev.commandto its absolute path.python: command not found: current releases discoverpython3and common absolute interpreter paths. Reconnect withhf-dev up; setpythonexplicitly only for unusual images.unable to flush session: current releases retry Mutagen and recreate the session automatically. Confirm the Job is still active withinfo --remoteif recovery fails.- Breakpoint is hollow or never hit: confirm the script reaches that code, ensure the local file was saved, and check
that the reported Transformers source is under
remote_root/src/transformers. - The Docker image already contains Transformers: this is expected. Bootstrap installs the synchronized checkout
editable, and debug startup refuses to proceed if
transformers.__file__resolves to the image copy. - First model load is slow: every new Job has a cold ephemeral cache by default. Later runs in the same Job reuse its local files.
- Opt-in Bucket cache is unexpectedly slow: safetensors are read through the remote FUSE mount. Start a new Job with
--no-cache; an already-running Job cannot have its volume removed in place. - Opt-in cache size nearly doubled after repeated F5: older releases could leave overlapping debug processes and a large
.incompletedownload. Stop debugging, then runhf cache prune --cache-dir /cache/huggingface/hub --yesin the remote shell. Release 0.1.6 and later prevent overlapping HF Dev debuggers for the same workspace. - Job started on the wrong hardware: inspect
hf-dev planand choose a GPU flavor explicitly beforeup. - Job was canceled in the Hub UI but Code OSS still shows active: local state is stale; use
info --remote, then run Start/Reconnect to replace the terminal Job. - SSH authentication fails: confirm a public key is registered on the Hub and that the token can write to the Job's namespace.
Maintaining and shipping the extension
Validate and package from the extension directory:
node --check extension.js
python -m json.tool package.json >/dev/null
vsce package --allow-missing-repository --no-dependencies
code-oss --install-extension hf-dev-0.1.7.vsix --force
Publish matching launcher and VSIX artifacts to the public release Bucket:
hf cp ~/.local/bin/hf-dev hf://buckets/OWNER/hf-dev-release/0.1.7/hf-dev
hf cp hf-dev-0.1.7.vsix hf://buckets/OWNER/hf-dev-release/0.1.7/hf-dev-0.1.7.vsix
Keep the launcher and VSIX under the same version folder because the extension delegates all remote lifecycle work to
the external hf-dev executable.
Xet Storage Details
- Size:
- 16.2 kB
- Xet hash:
- 58f32217c3d3e34005d8f1f92a1b1029f7ee6d98f59587bea1a55793ad884c1d
Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.