Skip to content

Access via AI Agents

AI coding agents running on your local machine, such as Claude Code, OpenCode, and Codex CLI, can execute remote commands over SSH. If they connect directly to login.ncshare.org, those commands run on the shared login node.

As with Access via VS Code, an SSH host alias backed by the auto-provisioning proxy directs those commands to a Slurm compute node instead.

Prerequisites

  • An NCShare account with SSH key access already configured. See Access via SSH if you haven't set this up yet.
  • A coding agent installed locally, e.g., OpenCode, Codex CLI, or Claude Code.

Step 1: Add a Dedicated SSH Host for Agent Sessions

Create a local SSH control-socket directory once,

mkdir -p ~/.ssh/sockets

Then add a Host block to ~/.ssh/config, using its own --name agent and a longer idle timeout than the interactive VS Code profiles. Replace NCSHARE_UID with your NCShare UID.

Host ncshare-agent
    User NCSHARE_UID
    ProxyCommand ssh -o ConnectTimeout=300 NCSHARE_UID@login.ncshare.org 'bash /usr/local/bin/ncshare-ssh-proxy.sh --name agent --partition common --idle-min 30'
    ConnectTimeout 300
    StrictHostKeyChecking no
    UserKnownHostsFile /dev/null
    LogLevel ERROR
    ServerAliveInterval 30
    ControlMaster auto
    ControlPersist 30m
    ControlPath ~/.ssh/sockets/%r@%h-%p

If your agent requires GPU access, add a second alias,

Host ncshare-agent-gpu
    User NCSHARE_UID
    ProxyCommand ssh -o ConnectTimeout=300 NCSHARE_UID@login.ncshare.org 'bash /usr/local/bin/ncshare-ssh-proxy.sh --name agent-gpu --partition gpu --gres gpu:h200:1 --idle-min 30'
    ConnectTimeout 300
    StrictHostKeyChecking no
    UserKnownHostsFile /dev/null
    LogLevel ERROR
    ServerAliveInterval 30
    ControlMaster auto
    ControlPersist 30m
    ControlPath ~/.ssh/sockets/%r@%h-%p

Step 2: Point your Agent at the Alias

All remote commands issued by the agent must target ncshare-agent or ncshare-agent-gpu, not login.ncshare.org. For example,

ssh ncshare-agent 'hostname'

and for a GPU command,

ssh ncshare-agent-gpu 'hostname && nvidia-smi'

Tell the agent to use these aliases through its project-level instruction file, as described below.

Add an Agent Instruction File

Many coding agents support a project-level instruction file such as AGENTS.md. Add the following content to the file in your project root.

AGENTS.md
# Remote Execution Policy: NCShare

- Never run commands directly on `login.ncshare.org`. It is a shared login node, not meant for computation.
- For any command that needs to run on NCShare, use:

      ssh ncshare-agent '<command>'

- For any command that needs to run on NCShare that requires GPUs, use:

      ssh ncshare-agent-gpu '<command>'

  This transparently provisions (or reuses) a Slurm compute job and proxies the connection to it -- you don't need to run `sbatch`/`salloc`/`srun` yourself.
- The first command after a period of inactivity may take several minutes while a new job is provisioned. This is expected; do not treat it as a failure.
- Do not run `scancel` on these jobs unless explicitly asked to. An idle watchdog ends the job automatically once nobody has run a command through `ncshare-agent` or `ncshare-agent-gpu` for a while.

Tool-specific filenames

The filename of the agent instruction file varies by tool. For example, Claude Code uses CLAUDE.md instead of AGENTS.md. Consult your agent's documentation and use the filename it expects.

Customizing the Agent Profile

Set these options as flags in the ProxyCommand in ~/.ssh/config.

Flag Default Meaning
--partition common Slurm partition(s) to submit to (comma-separated list)
--account (none) Slurm account, if required by your partition
--qos (none) Slurm QoS, if required
--gres none GPU request, e.g. gpu:1, gpu:h200:1; none = CPU-only
--cpus 4 CPUs to allocate
--mem 16G Memory to allocate
--time 8:00:00 Hard wall-time cap on the job
--idle-min 15 Minutes of no connection before idle cleanup (0 disables idle cleanup); use 30 for agentic workflows
--wait 240 Seconds to wait for a new job to start
--name vscode Use agent or agent-gpu to keep agentic workflows separate from other sessions
--log /dev/null Where to send Slurm job stdout/stderr (set a path to debug)

For example, add --mem 128G to the GPU profile's ProxyCommand to request 128 GB of memory.

--idle-min 0 disables idle-based cleanup

Setting --idle-min 0 prevents the watchdog from ending an idle job. The allocation remains active until you cancel it or it reaches the --time wall-time limit (8 hours by default).

Ending Sessions

After the shared SSH connection closes, the watchdog ends the job when its heartbeat has been stale for --idle-min minutes. With the configuration above, ControlPersist keeps that connection open for 30 minutes after the last command. You don't need to run scancel manually in normal use.

How it Works

Without this configuration, an agent that sends commands to login.ncshare.org runs them on the shared login node. Login nodes are intended for file management, job submission, and other lightweight tasks; computational workloads should run on compute nodes.

The required scripts, ncshare-ssh-proxy.sh and ncshare-session-watchdog.sh, are installed centrally in /usr/local/bin. When an agent connects through ncshare-agent or ncshare-agent-gpu,

  1. SSH connects to the login node and runs ncshare-ssh-proxy.sh through the configured ProxyCommand.
  2. The proxy reuses a running Slurm job for that profile or submits a new job and waits for its allocation.
  3. The proxy carries the SSH connection to port 22 on the allocated compute node.
  4. Commands sent through the alias therefore execute on the compute node rather than the login node.

The Slurm job runs ncshare-session-watchdog.sh. While the proxy connection remains open, the proxy updates a heartbeat file. After the connection closes and the heartbeat becomes stale, the watchdog ends the job after the configured --idle-min period. Setting --idle-min 0 disables idle-based cleanup. The job then runs until it is cancelled or reaches its wall-time limit.

Reusing SSH Connections

Agents commonly start a new ssh process for each remote command. The following options let those processes share one underlying SSH connection,

  • ControlMaster auto reuses an existing shared connection when one is available. The first connection creates it and later connections to the same host alias use it instead of reconnecting.
  • ControlPersist 30m keeps the shared connection open in the background for 30 minutes after the last command finishes.
  • ControlPath ~/.ssh/sockets/%r@%h-%p specifies the local socket used to find the shared connection. %r, %h, and %p expand to the remote username, host, and port, keeping connections for different aliases separate.

The first command must authenticate, run the proxy, and possibly wait for a Slurm allocation. Commands issued while the shared connection remains open reuse it immediately and do not rerun the proxy.

Connection persistence and idle cleanup

ControlPersist keeps the proxy connection and its heartbeat active. The --idle-min countdown effectively begins after the shared connection closes. With ControlPersist 30m and --idle-min 30, the allocation may remain active for approximately 60 minutes after the last command. Use a shorter ControlPersist value if faster cleanup is more important than connection reuse.

Troubleshooting

Every command seems to re-provision a new job

Check that each command uses the same host alias and --name, and that the gap between commands does not exceed the combined connection-persistence and idle periods. ControlMaster improves connection speed, but the proxy can still reuse a running Slurm job without it.

How do I confirm the agent isn't running on the login node?

Ask the agent to run ssh ncshare-agent hostname. It should print a compute node name (e.g., compute-11), never a login node name.

Acknowledgements

This guide was adapted from PSC's Launching Remote IDEs on Bridges-2 Compute Nodes documentation and was enhanced with the help of Joe Shamblin at Duke University.