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.

Note

If you are using a coding agent through a VS Code Plugin, the set up detailed in Access via VS Code is sufficient as the AI processes will run on a compute node.

Running an agent inside an interactive session

You can also SSH to NCShare, start an interactive session (or an interactive GPU session), and launch the agent from that shell. The agent and every command it runs then stay on the allocated compute node, limited to the CPUs, memory, and time you requested, so the SSH alias setup below is not needed. Start the agent only after the prompt shows a compute node hostname, never on the login node. The agent exits when the job reaches its time limit.

Moving agent commands off the login node is a prerequisite for running them here, not permission to run anything. How you supervise an agent on shared infrastructure matters as much as where its commands land.

Important

Before setting up an agent, read the AI Use Policy. It sets out which agentic workflows are acceptable on NCShare, which tools are not permitted, which permission modes to avoid, and what you remain accountable for.

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 StrictHostKeyChecking=accept-new %r@login.ncshare.org bash /usr/local/bin/ncshare-ssh-proxy.sh --name agent
    StrictHostKeyChecking accept-new
    UserKnownHostsFile /dev/null
    ServerAliveInterval 30
    ControlMaster auto
    ControlPersist 30m
    ControlPath ~/.ssh/sockets/%r@%h-%p

If you have multiple SSH keys, specify the key to use by adding IdentityFile <path-to-ssh-key> to the Host block above. For example,

IdentityFile ~/.ssh/id_ed25519

Warning

We encourage encrypting your SSH private key with a strong passphrase. Never share your SSH private key with anyone.

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

Host ncshare-agent-gpu
    User NCSHARE_UID
    ProxyCommand ssh -o StrictHostKeyChecking=accept-new %r@login.ncshare.org bash /usr/local/bin/ncshare-ssh-proxy.sh --name agent-gpu --partition interactive-gpu,gpu --gres gpu:h200:1 --time 1:00:00
    StrictHostKeyChecking accept-new
    UserKnownHostsFile /dev/null
    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. You do not run these ssh commands yourself; the agent issues them as it works. Tell the agent to use the aliases through its instruction file, as described below.

Add an Agent Instruction File

Many coding agents read a project-level instruction file such as AGENTS.md in your project root. Most also read a global file that applies to every project, so you do not have to repeat this in each repository,

Agent Project file Global file
Claude Code AGENTS.md or CLAUDE.md ~/.claude/CLAUDE.md
Codex CLI AGENTS.md ~/.codex/AGENTS.md
OpenCode AGENTS.md ~/.config/opencode/AGENTS.md

Use the global file if you work on NCShare from more than one project, and the project file if only that project connects to NCShare. Add the following content to whichever file you choose.

Claude Code and AGENTS.md

Claude Code reads a project AGENTS.md only when there is no CLAUDE.md or CLAUDE.local.md in that directory or above it, and it has no global AGENTS.md. If your project already has a CLAUDE.md, put this content there instead, and use ~/.claude/CLAUDE.md for the global copy.

AGENTS.md
# Remote Execution Policy: NCShare

- Never run commands directly on `login.ncshare.org`. It is a shared login node and must not run your commands.
- 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 seconds 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.

## SSH control socket directory

`ncshare-agent` and `ncshare-agent-gpu` use SSH connection multiplexing with `ControlPath ~/.ssh/sockets/%r@%h-%p`. `ssh` does not create parent directories for that path, so if `~/.ssh/sockets` is missing, every connection fails immediately with:

    unix_listener: cannot bind to path /Users/USERNAME/.ssh/sockets/USERNAME@ncshare-agent-22.<random>: No such file or directory

This is a local setup problem, not a NCShare or Slurm problem — do not retry, do not provision a job. Fix it with:

    mkdir -p ~/.ssh/sockets && chmod 700 ~/.ssh/sockets

Mode 700 is required. A live control socket accepts new channels on an already-authenticated session without presenting any credential, so anyone able to reach it inherits the connection.

## Shared Cluster Conduct

NCShare is shared research infrastructure. Full policy:
https://userguide.ncshare.org/about/aipolicy/

- Right-size resource requests and do not run work that degrades the cluster for other users.
- Keep approval prompts on. Do not use or ask for permission-bypass modes such as
  `--dangerously-skip-permissions`, `bypassPermissions`, or blanket tool approval.
- Confirm before destructive or large-scale actions: deleting or overwriting data, mass file
  edits, bulk job submission, or cancelling jobs you did not start.
- Do not install, run, expose, or proxy OpenClaw on NCShare nodes, interactive sessions, Open
  OnDemand environments, or NCShare storage.
- No sensitive data is permitted on NCShare. Do not move restricted or identifiable data onto
  the cluster.

These instructions are a starting point. The AI Use Policy applies whether or not your agent reads them, and you remain accountable for what the agent does under your account.

Step 3: Interact with the Agent

Launch the agent on your local machine and ask it to do work on NCShare. The example below prompts the agent to report your current jobs on the cluster.

Claude Code running squeue through the ncshare-agent alias in response to a prompt about current jobs

The agent runs the command through the ncshare-agent alias, which provisions a Slurm job and proxies the connection to a compute node. The output returns to the agent, which reports it in the chat window.

Claude Code summarizing the jobs returned by squeue

The agent's own proxy job, named agent-NCSHARE_UID, appears in the queue alongside your other jobs.

Keep prompting the agent to design, submit, and monitor workflows, and it continues to run those commands from the compute node. In the example below, the agent writes a Slurm array job script, copies it to NCShare, and submits it with sbatch.

Claude Code writing an array job script and submitting it through the ncshare-agent alias

The agent then waits for the array job to finish and reports the output each task wrote.

Claude Code reporting ten completed array tasks and the contents of each task output file

You can also run several agent sessions at once; sessions that use the same alias share one Slurm job. Once no session has sent a command for the configured --idle-min period, the watchdog ends the allocation. The next prompt provisions a new job automatically.

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 2 CPUs to allocate
--mem 4G 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)
--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.

To end a session immediately instead of waiting for the idle timeout, or if you set --idle-min 0, SSH to the login node directly and cancel the job,

ssh NCSHARE_UID@login.ncshare.org
squeue -u $USER
scancel <jobid>

How it Works

Without this configuration, an agent that sends commands to login.ncshare.org runs them on the shared login node. The login node is a shared entry point, intended for file management and job submission, not for running an agent's commands. An agent decides on its own what to execute, so a session that begins with a status check can end up running builds, test suites, and searches across large directories.

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.

The diagram below traces a single connection, from the ProxyCommand on the login node through to the agent's commands running inside the Slurm job.

Connection flow from a local client to an NCShare compute node through ncshare-ssh-proxy.sh and ncshare-session-watchdog.sh

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 15, the allocation may remain active for approximately 45 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 of Duke CS.