Configuring VS Code and Cursor¶
This also applies to Cursor
Cursor is a fork of VS Code and uses the same Remote-SSH mechanism, so the same configuration described on this page applies to it as well.
This documentation is only useful if you plan to use VS Code to edit files stored in the cluster file system remotely. You should also check the docs in Remote Editing and specially the specific section related to how to configure the VS Code SSH plugin
Read this page before connecting VS Code to the cluster
Using VS Code is only allowed in the dedicated login node vscode.scicore.unibas.ch
The login nodes are a shared resource. Your home directory lives on a network filesystem (NFS) that is shared by every user on the cluster.
With its default settings, the VS Code Remote-SSH extension generates a very large amount of filesystem traffic against that NFS share: it installs ~300 MB of runtime into your home directory, continuously watches and re-scans your files, and indexes every Python environment it can find.
When dozens of users do this at once, the shared filesystem saturates and everybody’s login node becomes slow — including yours.
The settings on this page are mandatory. They take about five minutes to apply and will make the VS Code sessions noticeably faster for you and for every other user working in the same login node.
If you have already used VS Code before in the cluster, it’s recommended that you follow these steps before continuing with this documentation:
- Close VS Code on your computer
- Terminate all your running vscode processes on
vscode.scicore.unibas.chwith
- Delete your current config from the cluster filesystem executing
rm -fr ~/.vscode-server/andrm -fr ~/.cursor-server/in any login node
Why VS Code is a problem in the cluster¶
VS Code’s remote development model is designed for a machine with a local/fast disk, not for a shared login node with a network home directory. Three things go wrong:
| What VS Code does | Why it hurts here |
|---|---|
Installs ~/.vscode-server (node runtime, extensions, logs, state databases, IPC sockets) into $HOME |
Every one of those reads and writes crosses the network to the NFS server |
| Watches your workspace for file changes | inotify does not work over NFS, so the watcher silently falls back to polling — repeatedly stat-ing thousands of files |
| Indexes your Python environments (Pylance, Jupyter) | A single conda environment is ~100 000 small files. Indexing it over NFS is brutal |
Multiply that by every concurrent VS Code user and the result is the slow
ls, slow cd and slow logins that you have probably already noticed.
Step 1 — Move the VS Code server off NFS¶
This is the single most important change on this page. By default VS Code
installs its server into ~/.vscode-server, which is on NFS. We want it on the
login node’s local disk instead.
On your own machine (not the cluster), open the VS Code Settings JSON:
- Press
f1(orctrl+shift+p(Windows) /cmd+shift+p(Mac)) - Run Preferences: Open User Settings (JSON)
Add the following, replacing USERNAME with your cluster username:
{
"remote.SSH.serverInstallPath": {
"vscode.scicore.unibas.ch": "/scratch/vscode/USERNAME"
},
"remote.SSH.connectTimeout": 120
}
Adjust the host name vscode.scicore.unibas.ch if needed
The key pointing to “/scratch/vscode/USERNAME” (“vscode.scicore.unibas.ch” above) must match exactly the Host alias you use in your ~/.ssh/config to connect to the cluster. If you customized the host alias of “vscode.scicore.unibas.ch” to be hpc, for example, then the configuration line above should change to "hpc": "/scratch/vscode/USERNAME", replacing USERNAME with your cluster username.
Then, once, SSH to the vscode login node from your terminal and create the following directory on the scratch folder:
# Local machine terminal
ssh USERNAME0000@vscode.scicore.unibas.ch
# VS Code login node
mkdir -p /scratch/vscode/$USER
chmod 700 /scratch/vscode/$USER
ln -s /scratch/vscode/$USER/.vscode-server ~/.vscode-server
ln -s /scratch/vscode/$USER/.cursor-server ~/.cursor-server
Local disk is not backed up and not shared
/scratch is per node and may be purged at any time. Never put
anything you care about there. VS Code will simply reinstall its server if
the directory disappears.
Step 2 — Tame the file watcher and the indexers¶
Still on your local machine, in the same settings.json, add:
{
"files.watcherExclude": {
"**/.git/objects/**": true,
"**/.git/subtree-cache/**": true,
"**/node_modules/**": true,
"**/.conda/**": true,
"**/conda/**": true,
"**/miniconda3/**": true,
"**/venv/**": true,
"**/.venv/**": true,
"**/site-packages/**": true,
"**/__pycache__/**": true,
"**/.mypy_cache/**": true,
"**/.pytest_cache/**": true,
"**/data/**": true,
"**/results/**": true
},
"search.followSymlinks": false,
"search.exclude": {
"**/node_modules": true,
"**/site-packages": true,
"**/data": true,
"**/results": true
},
"python.analysis.indexing": false,
"python.analysis.userFileIndexingLimit": 0,
"python.analysis.autoSearchPaths": false,
"git.autofetch": false,
"git.autorefresh": false,
"telemetry.telemetryLevel": "off",
"extensions.autoUpdate": "off",
"extensions.autoCheckUpdates": false
}
What each group does:
files.watcherExclude— stops VS Code polling directories that never change in ways you care about. Add your own large data directories.search.followSymlinks: false— prevents a full-text search from wandering out of your project and across the whole filesystem via a symlink.python.analysis.*— stops Pylance from walking every Python environment on the system. You keep syntax checking and completion for files you actually open; you lose “go to definition” into third-party libraries you have not opened.git.autofetch/git.autorefresh— stops agit status(and possibly a network fetch) firing every few seconds against a repository on NFS.extensions.autoUpdate— stops extensions being silently re-downloaded and re-unpacked into your home directory in the background.
Step 3 — Keep your workspace small¶
Open the project, not your home directory
Never do File → Open Folder on /home/USERNAME.
VS Code will try to watch and index everything you own. Open the specific
project directory you are working on: ~/projects/my-analysis, not ~.
Other habits that help a lot:
- Close the remote window when you stop working. A forgotten VS Code window keeps polling all night. Use File → Close Remote Connection, don’t just close your laptop lid.
- Don’t open more remote windows than you need. Each one starts its own set of extension host processes.
- Keep large datasets out of the workspace tree, or add them to
files.watcherExcludeas shown above.
I don’t want these settings on my local projects¶
The configuration in Step 2 is written into your User Settings, so it applies
to every VS Code window you open — local ones included. If you also use VS Code
for work that is unrelated to the cluster, you may not want git.autofetch
disabled or Pylance indexing turned off everywhere.
Two supported ways to scope the settings to your cluster work only. Both work; pick whichever fits your habits.
remote.SSH.* always stays in local User Settings
remote.SSH.serverInstallPath and remote.SSH.connectTimeout are read by
your local VS Code before the connection is made, so they cannot live
on the server. They are already host-scoped (serverInstallPath is keyed by
host name), so leaving them in User Settings is harmless.
Option A — A dedicated “scicore” profile¶
A profile is a named bundle of settings, extensions and UI state. Settings put in a profile only apply to windows using that profile.
- File → Preferences → Profiles → Create Profile…
- Name it
scicore. Choose Empty Profile, or copy from your current one. - With the
scicoreprofile active, run Preferences: Open User Settings (JSON) and paste the Step 2 block there. - Connect to
vscode.scicore.unibas.ch. In that remote window, select the profile via File → Preferences → Profiles → scicore.
VS Code remembers the profile per folder/workspace, so the next time you open
that same remote folder it comes back with the scicore profile already
applied. Your other projects keep your normal settings.
Extensions too
A profile also controls which extensions are enabled. An empty scicore
profile with only Python + Jupyter installed means fewer extension hosts
running on the login node — which is exactly what we want.
Option B — Put the settings on the server¶
Settings can also live on the cluster side, next to the code they apply to.
Per project — create .vscode/settings.json inside the project directory on
the cluster. This is the best place for the excludes that are really properties
of the project (**/data/**, **/results/**):
{
"files.watcherExclude": {
"**/.git/objects/**": true,
"**/node_modules/**": true,
"**/.conda/**": true,
"**/venv/**": true,
"**/.venv/**": true,
"**/site-packages/**": true,
"**/__pycache__/**": true,
"**/.mypy_cache/**": true,
"**/.pytest_cache/**": true,
"**/data/**": true,
"**/results/**": true
},
"search.followSymlinks": false,
"search.exclude": {
"**/site-packages": true,
"**/data": true,
"**/results": true
},
"python.analysis.indexing": false,
"python.analysis.userFileIndexingLimit": 0,
"python.analysis.autoSearchPaths": false,
"git.autofetch": false,
"git.autorefresh": false
}
You have to repeat this in every project — but you can commit it to the repository, which means your collaborators get it for free.
For every project on the cluster at once — use the machine settings file, which applies to all windows connected to that host. From a VS Code terminal on the login node, run Preferences: Open Remote Settings (SSH: vscode.scicore.unibas.ch), or write the file directly:
mkdir -p /scratch/vscode/$USER/data/Machine
$EDITOR /scratch/vscode/$USER/data/Machine/settings.json
Paste the same JSON block as above.
Machine settings live on /scratch and can be purged
If you followed Step 1, the machine settings file sits under
/scratch/vscode/$USER/data/Machine/, which is not backed up and is wiped
when the node is cleaned. Keep a copy somewhere safe and re-push it after a
server reinstall:
Caveat: settings that cannot be scoped by machine, project or profile
telemetry.telemetryLevel, extensions.autoUpdate and
extensions.autoCheckUpdates are application-scoped
and can only be set in the settings file from the Default profile.
They are ignored in project and machine settings files (VS Code greys them out).
Set them in your local User Settings, as neither Option A nor Option B can
override them.
What happens if I ignore this¶
We monitor per-user I/O and CPU on the login nodes. Sessions that generate sustained, excessive load will be throttled automatically, and repeat offenders will have their processes terminated without warning. This is not a punishment — a single misconfigured VS Code session can measurably degrade the login node for dozens of other people.
If you get throttled, work through this page and reconnect.
Complete reference configuration¶
For convenience, here is everything from steps 1 and 2 in a single block. Merge
it into your local User Settings (JSON) and change USERNAME and the host
name. If you would rather not have these settings apply to your local projects,
see I don’t want these settings on my local
projects.
{
"remote.SSH.serverInstallPath": {
"vscode.scicore.unibas.ch": "/scratch/vscode/USERNAME"
},
"remote.SSH.connectTimeout": 120,
"files.watcherExclude": {
"**/.git/objects/**": true,
"**/.git/subtree-cache/**": true,
"**/node_modules/**": true,
"**/.conda/**": true,
"**/conda/**": true,
"**/miniconda3/**": true,
"**/venv/**": true,
"**/.venv/**": true,
"**/site-packages/**": true,
"**/__pycache__/**": true,
"**/.mypy_cache/**": true,
"**/.pytest_cache/**": true,
"**/data/**": true,
"**/results/**": true
},
"search.followSymlinks": false,
"search.exclude": {
"**/node_modules": true,
"**/site-packages": true,
"**/data": true,
"**/results": true
},
"python.analysis.indexing": false,
"python.analysis.userFileIndexingLimit": 0,
"python.analysis.autoSearchPaths": false,
"git.autofetch": false,
"git.autorefresh": false,
"telemetry.telemetryLevel": "off",
"extensions.autoUpdate": false,
"extensions.autoCheckUpdates": false
}
Troubleshooting¶
How do I check it worked?
After reconnecting, run this in the VS Code terminal:
[ "$(readlink ~/.vscode-server)" = "/scratch/vscode/$USER/.vscode-server" ] && echo ok || echo wrong - this should be a symlink
ls -d /scratch/vscode/$USER/.vscode-server && echo "OK - on local disk"
[ "$(readlink ~/.cursor-server)" = "/scratch/vscode/$USER/.cursor-server" ] && echo ok || echo wrong - this should be a symlink
ls -d /scratch/vscode/$USER/.cursor-server && echo "OK - on local disk"
If ~/.vscode-server or ~/.cursor-server still exists from a previous session, delete it and create a symlink:
rm -rf ~/.vscode-server
rm -rf ~/.cursor-server
ln -s /scratch/vscode/$USER/.vscode-server ~/.vscode-server
ln -s /scratch/vscode/$USER/.cursor-server ~/.cursor-server
This may take several minutes — it contains tens of thousands of files, which is precisely the point.
Connection hangs at Checking .log and .pid for a running server
This is the classic symptom of .vscode-server sitting on NFS: the lock
check blocks on the network filesystem and never returns. Apply
Step 1, then remove the old
directory:
Connection worked yesterday and now fails
Stale server state, often after a node reboot cleared /scratch, or
after a VS Code update. Remove the server directory and reconnect:
Unable to watch for file changes in this large workspace (ENOSPC)
You have opened too large a folder. Open a narrower directory
(Step 3) and check your
files.watcherExclude covers your data directories.
Note that files.watcherExclude is known not to apply reliably to paths
outside your workspace — the real fix is to not open those paths.
I disabled indexing and lost go to definition in libraries
That is the trade-off. If you need it for a specific project, re-enable it in
that project’s .vscode/settings.json only — never globally:
Please turn it off again when you are done.
My settings are not being applied in the remote window
Check which layer is winning. Run Preferences: Open Settings (UI), search for the setting, and look at the tab bar (User / Remote / Workspace) — the active tab shows where the effective value comes from. More specific layers override less specific ones:
User < Remote (Machine) < Workspace < Folder
If you are using a profile (Option A), also confirm the right profile is active for the window: the profile name is shown in the bottom-left gear menu.