Public course previewThis is not your assigned passport. No identity, answers, or completion progress are stored here.How to start your passport
Handbook / reference

reference

Claude Code On Euler

Claude Code is an AI coding agent from Anthropic that runs in a terminal. It can read your project, propose edits, and run commands that you approve. This page runs it on an Euler compute node reserved by a Slurm job, inside tmux (a program that keeps a terminal session alive after you disconnect). Your session survives a closed laptop or a dropped SSH connection.

Goal: start Claude Code on a Slurm compute allocation, detach and reattach safely, and give it the lab rules as context.

Prerequisites:

  • The final public-key-only config-ok alias test in Euler access passes.
  • GitHub access from Euler works, as in step 2 of GitHub code sync. You need it to clone the onboarding repository in step 4.
  • You have a Claude account that includes Claude Code (Pro, Max, Team, Enterprise, or Console). The free plan does not include it. Lab-funded access follows the internal lab handbook. Read Personal AI accounts and costs before you pay for anything yourself.
  • You have read the AI coding agents boundaries and the Data and AI policy. Use only data that the information owner has approved for this service.

New to text commands? Read how to open a terminal and run one command first.

Execution context: every block on this page runs on an Euler login node - Bash (after ssh euler), unless the heading says otherwise. Claude Code itself runs on a compute node that claude-start reserves for you.

Understand Before Accepting AI Output#

  • Human intent: you decide the task. Claude Code proposes; you approve.
  • Context: step 4 points Claude Code at the lab rules in this repository.
  • Constraints: do not let it submit Slurm jobs, start GPU work, install software, commit, or push unless you asked for that exact action.
  • Verification: read every command before you approve it. Read every diff before you stage it.
  • Review criteria: you must be able to explain each accepted change and each submitted job request in your own words.

1. Install Claude Code#

The eth_proxy module gives Euler nodes access to the internet. Login nodes usually have access already. Compute nodes need the module.

module load eth_proxy
curl -fsSL https://claude.ai/install.sh | bash
grep -qxF 'export PATH="$HOME/.local/bin:$PATH"' ~/.bashrc || echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.bashrc
grep -qxF 'module load eth_proxy 2>/dev/null' ~/.bashrc || echo 'module load eth_proxy 2>/dev/null' >> ~/.bashrc
source ~/.bashrc
claude --version

Expected output: the last line prints a version number such as 2.1.211 (Claude Code). The installer puts the program at ~/.local/bin/claude. You can run this block again safely. It does not add duplicate lines to ~/.bashrc.

2. Log In Once#

claude

Type /login, open the link in the browser on your computer, and paste the code back into the terminal. When Claude Code shows its prompt, type /exit.

Log in only. Do not start real work on the login node. Login nodes are shared by all Euler users.

3. Install The Helper Commands#

This block writes three commands to ~/.claude-euler.sh and loads that file from ~/.bashrc:

  • claude-start reserves a compute node and opens Claude Code on it.
  • claude-list shows your running Claude Code jobs.
  • claude-reconnect attaches to a running job again.

The defaults are small on purpose: 2 CPU cores, 4 GiB per core, 2 hours, on es_fuge. You can run this block again to update the file.

cat > ~/.claude-euler.sh <<'CLAUDE_EULER'
# Claude Code on Euler helpers. Source: IDEAL Lab onboarding,
# docs/reference/euler/claude-code.md

claude-start() {
    local gpu=false time_hours=2 account=es_fuge
    local usage="Usage: claude-start [--time HOURS] [--account es_fuge|public] [--gpu]"
    while [[ $# -gt 0 ]]; do
        case $1 in
            --gpu) gpu=true; shift ;;
            --time)
                if [[ $# -lt 2 || ! "$2" =~ ^[0-9]+([.][0-9]+)?$ ]]; then
                    echo "STOP: --time needs a number of hours, for example 1.5"; echo "$usage"; return 1
                fi
                time_hours=$2; shift 2 ;;
            --account)
                if [[ $# -lt 2 || ! "$2" =~ ^[A-Za-z0-9_]+$ ]]; then
                    echo "STOP: --account needs an account name, for example es_fuge"; echo "$usage"; return 1
                fi
                account=$2; shift 2 ;;
            *) echo "$usage"; return 1 ;;
        esac
    done
    if $gpu && [[ "$account" == "public" ]]; then
        echo "STOP: the public share has no GPUs. Use --account es_fuge for --gpu."
        return 1
    fi
    local mins
    mins=$(awk -v h="$time_hours" 'BEGIN { printf "%d", h * 60 }')
    if [[ "$mins" -lt 1 ]]; then
        echo "STOP: --time must be a positive number of hours, for example 1.5"
        return 1
    fi
    local time_fmt
    time_fmt=$(printf "%02d:%02d:00" $((mins / 60)) $((mins % 60)))
    local name="ccc_$(date +%H%M)"
    local opts=(--cpus-per-task=2 --mem-per-cpu=4G)
    if $gpu; then
        name="ccg_$(date +%H%M)"
        opts=(--cpus-per-task=4 --mem-per-cpu=4G --gpus=rtx_4090:1)
    fi
    local logdir="$HOME/.claude-euler-logs"
    mkdir -p "$logdir" && chmod 700 "$logdir"
    local jobid
    jobid=$(sbatch --parsable --account="$account" --job-name="$name" \
        --time="$time_fmt" --output="$logdir/%j.out" "${opts[@]}" <<'JOB'
#!/bin/bash -l
module load eth_proxy || exit 1
sock="job_$SLURM_JOB_ID"
tmux -L "$sock" new-session -d -s claude "claude" || exit 1
while tmux -L "$sock" has-session -t claude 2>/dev/null; do sleep 10; done
JOB
)
    if [[ -z "$jobid" ]]; then
        echo "sbatch failed"
        return 1
    fi
    echo "Job $jobid ($name, $account, $time_fmt). Waiting for a node..."
    while true; do
        local state
        state=$(squeue -j "$jobid" -h -o "%T" 2>/dev/null)
        if [[ "$state" == "RUNNING" ]]; then
            claude-reconnect "$jobid"
            return
        fi
        if [[ -z "$state" ]]; then
            echo "Job ended or was cancelled"
            return 1
        fi
        sleep 2
    done
}

claude-list() {
    squeue -u "$USER" -h -o "%i %j %T %M %R" | grep -E "^[0-9]+ cc[gc]_" || echo "No claude jobs"
}

claude-reconnect() {
    local jobid=$1
    if [[ ! "$jobid" =~ ^[0-9]+$ ]]; then
        claude-list
        return 1
    fi
    local state node
    read -r state node < <(squeue -j "$jobid" -h -o "%T %N")
    if [[ "$state" != "RUNNING" || -z "$node" ]]; then
        echo "Job $jobid is not running"
        return 1
    fi
    for _ in $(seq 1 20); do
        ssh -t "$node" "tmux -L job_$jobid attach -t claude" 2>/dev/null && return 0
        sleep 2
    done
    echo "Failed to attach"
    return 1
}
CLAUDE_EULER
grep -qxF 'source ~/.claude-euler.sh' ~/.bashrc || echo 'source ~/.claude-euler.sh' >> ~/.bashrc
source ~/.bashrc
type claude-start >/dev/null && echo "OK: helpers installed"

Expected output: OK: helpers installed.

4. Give Claude Code The Lab Rules#

Claude Code reads ~/.claude/CLAUDE.md at the start of every session. This step clones this onboarding repository to your Euler home and points that file at the repository's agent instructions and linked research briefing. The reference asks Claude Code to read the relevant lab rules rather than copying them. Follow Give your AI agent the lab context for project instructions and the fresh-session check; a reference alone does not prove that the files were read.

The repository is private to the IDEAL Lab GitHub organization. If the clone fails with Repository not found, ask lab IT for access.

(
  cd "$HOME" || exit 1
  if [ -d "$HOME/onboarding-IT/.git" ]; then
    git -C "$HOME/onboarding-IT" pull --ff-only
  else
    git clone git@github.com:IDEALLab/onboarding-IT.git
  fi
)

If step 2 of GitHub code sync made you create the dedicated Euler key, run this clone instead:

(
  cd "$HOME" || exit 1
  GIT_SSH_COMMAND="ssh -i $HOME/.ssh/id_ed25519_github_euler -o IdentitiesOnly=yes" git clone git@github.com:IDEALLab/onboarding-IT.git || exit 1
  git -C "$HOME/onboarding-IT" config --local core.sshCommand "ssh -i $HOME/.ssh/id_ed25519_github_euler -o IdentitiesOnly=yes"
)

Then add the pointer to your personal Claude Code instructions:

mkdir -p ~/.claude
grep -qF 'onboarding-IT/AGENTS.md' ~/.claude/CLAUDE.md 2>/dev/null || cat >> ~/.claude/CLAUDE.md <<'CLAUDE_MD'

# IDEAL Lab rules
- Before any lab operation on Euler (Slurm jobs, storage, GitHub, Python
  environments, Weights & Biases, Hugging Face), read
  ~/onboarding-IT/AGENTS.md and the research briefing it links to.
- Do not submit Slurm jobs, start GPU work, install software, commit, or push
  unless I ask for that exact action in this session.
CLAUDE_MD
tail -n 8 ~/.claude/CLAUDE.md

Expected output: the last lines of ~/.claude/CLAUDE.md show the IDEAL Lab rules section once. Run the first block again from time to time to get current lab rules.

5. How Do I Use It?#

Start a session. The command waits until Slurm gives you a node, then opens Claude Code:

claude-start --time 1.5      # 1.5 hours on es_fuge
claude-start                 # 2 hours (default)
claude-start --account public --time 1

Use --account public only for CPU work that fits the public-share limits.

GPU sessions are for short, approved debugging only. Ask your supervisor first. Use sbatch for training. See the GPU rules.

claude-start --gpu --time 0.5   # one RTX 4090, 30 minutes

Detach (Claude Code keeps working): press Ctrl-b, release both keys, then press d.

Reattach later:

claude-list

The first column is the job ID. Pass it to claude-reconnect, for example:

claude-reconnect 12345678

Stop: type /exit in Claude Code. The job ends when Claude Code exits or the time runs out. To stop a job that you cannot attach to:

scancel 12345678

Data, Jobs, And Sessions#

These pages are the canonical lab procedures for data, code, and jobs:

The research briefing named in step 4 already links to these procedures. Use the lab-context guide to verify that your session reads the briefing and the files relevant to its task. You do not need a second copy of the procedure list in your instructions.

Claude Code saves each conversation under ~/.claude/projects/, in one folder per working directory. In the same directory, claude --continue opens the most recent conversation and claude --resume shows a list.

Common Failures And Safe Recovery#

  • claude: command not found: run source ~/.bashrc. If that does not help, run the step 1 block again.
  • ECONNREFUSED or no network inside Claude Code: the compute node did not load eth_proxy. Check that ~/.bashrc contains module load eth_proxy 2>/dev/null.
  • claude-start waits a long time: the job is pending. Run claude-list; the last column shows the reason. See pending reasons.
  • Job ended or was cancelled: run sacct -j 12345678 with your job ID and read the state. Then read the job log, for example cat ~/.claude-euler-logs/12345678.out.
  • Failed to attach: Claude Code may have exited on the node. Run claude-list. Cancel the job with scancel if it still runs, then start a new one.
  • Session crashes with Bus error: your Euler home is network storage shared by all nodes. An automatic update on another node can remove the program version that this session uses. Start a new session.
  • Claude Code asks to log in again: run claude on the login node, type /login, then /exit.

Primary Sources#

Verified: 2026-10-08. Review by: 2027-01-06. Owner: IDEAL Lab IT.