KAUST Ibex HPC Operations
Deploy, submit, monitor, and retrieve results on Ibex (SLURM) over SSH, on the
user's behalf. Top priority: never do anything that could violate cluster
policy or draw administrator attention (see "Compliance red lines"). When in
doubt, take the slower, by-the-book path — the user's account is not worth any
shortcut.
0. Preflight — run this before any Ibex work
All connection details live on the local machine in ~/.config/kaust-ibex/config
(shell syntax, KEY=value). This skill contains no account information; the
config file is the single source of truth. Start every Ibex session with:
bash <this-skill-dir>/scripts/preflight.sh
Branch on its output:
READY host=... node=... — connection works; proceed. source the config file
to get:
IBEX_HOST — ssh target (an alias or user@host). Use it everywhere:
ssh "$IBEX_HOST" ..., rsync ... "$IBEX_HOST":...
IBEX_USER — the user's KAUST login
IBEX_PROJECT_ROOT — durable project storage root, e.g.
/ibex/user/<username> (a project's own remote path, if recorded in that
project's CLAUDE.md, takes precedence)
NO_CONFIG — first use on this machine; run "Guided setup" below.
NO_PASSWORDLESS — key-based login is broken, or the KAUST network route is
unreachable (Ibex login nodes are typically only reachable on the KAUST
network or via VPN). Stop all automated Ibex operations. Tell the user:
passwordless SSH is a prerequisite for automation — set up a key
(ssh-keygen + ssh-copy-id <host>), confirm the KAUST VPN/network route is
active, then retry. Never type passwords for the user or try to work around
authentication.
Guided setup (only on NO_CONFIG)
- Scan for candidates:
grep -B1 -A4 -i 'ibex.kaust.edu.sa' ~/.ssh/config.
- If nothing is found or multiple candidates exist, ask the user which Host to
use and what their KAUST login is. Never guess account information.
- Test passwordless login:
ssh -o BatchMode=yes -o ConnectTimeout=10 <host> 'echo OK && hostname'.
- On success, write
~/.config/kaust-ibex/config (template in the header of
scripts/preflight.sh) and chmod 600 it. Also probe for the durable
project root: ssh <host> 'ls -d /ibex/user/$USER 2>/dev/null' and record
it in IBEX_PROJECT_ROOT if present.
- On failure, follow NO_PASSWORDLESS above; do not write
IBEX_PASSWORDLESS=yes.
1. Compliance red lines (each one is a hard constraint)
- Login/frontend nodes are for light operations only: ls / cat / squeue /
sbatch / editing small files / small scp. Anything that burns CPU, memory,
or heavy IO — installing packages, building conda/mamba environments,
extracting large archives, bulk-deleting big directories, data processing,
running any program — must go through a compute node, either an
interactive allocation (
salloc/srun --pty) or a batch job (sbatch).
- Every Ibex action must trace back to an explicit user request. Once the
user says "run X on Ibex", the deploy → submit → monitor → retrieve chain
for that task can run autonomously; actions outside that scope (touching
other directories, cancelling unrelated jobs) are off-limits.
- Destructive operations require a confirmed list first: bulk
rm,
overwriting existing remote results, scancel on jobs not submitted in
this task, killing a persistent interactive/dev-server allocation another
task may still need.
- Rate-limit polling: status-check loops at ≥ 60-second intervals (don't
hammer
squeue). Batch several remote commands into one ssh call
(ssh host 'cmd1; cmd2; cmd3') — fewer connections, lower latency.
- Stay well below quota ceilings. Check current storage usage
(
df -h /ibex/user or the cluster's quota command) before large writes —
/ibex/user can run close to full, and a full filesystem blocks writes for
every user sharing it, not just the current job.
- No restricted data on the cluster. Never store or enter passwords/API
keys on the user's behalf — those belong in a project
.env. Treat any
logs from persistent dev-server-style jobs (e.g. remote IDE servers) as
potentially sensitive if they can embed a generated access token/password.
2. Status checks (when the user asks "how are my jobs doing?")
Grab everything in one ssh call:
ssh "$IBEX_HOST" 'squeue --me; echo ---; sacct -X --starttime today -o JobID,JobName%20,State,Elapsed,ExitCode | tail -30'
| To see |
Command (inside ssh) |
| Running / queued jobs |
squeue --me |
| Recent job outcomes (incl. failures) |
sacct -X --starttime <date> -o JobID,JobName%20,State,Elapsed,ExitCode |
| Resource efficiency of a finished job |
seff <jobid> |
| Storage usage |
df -h /ibex/user (or the cluster's official quota command) |
| Partition / node states |
sinfo |
| GPU availability |
sinfo -o "%n %G %f %t" (single batch partition; filter by feature/GRES) |
| Job logs |
tail -50 <submit-dir>/slurm-<jobid>.out (or the path set via --output) |
| Recover a job's real account/QOS/paths |
scontrol show job <id> |
Failure triage order: tail of the .err file → sacct State/ExitCode (OOM →
more memory, TIMEOUT → more time, NODE_FAIL/PREEMPTED → just resubmit) →
seff to see whether resources were undersized.
3. Task routing
- Deploying code / transferring files / setting up environments (conda, uv) /
storage & quota issues → read references/deploy.md first.
- Writing SLURM scripts / submitting jobs / GPU-type-aware requests / debugging
jobs / interactive & persistent-dev-server sessions → read
references/slurm.md first.
- Both at once (the common "run X on Ibex") → read both, execute in
deploy → slurm order.
- Something in this skill turned out wrong or missing, or the user says
"file that as an issue" → §7 (draft an issue for the skill's repository;
file only after the user confirms).
4. Using Ibex inside a loop (submit → wait → retrieve → iterate)
Standard loop skeleton:
- Deploy changed files (full dependency-chain check, see deploy.md), then
submit (see slurm.md).
- Wait in the background, polling at ≥ 60s intervals (scale up to 5–10
minutes for long jobs):
ssh "$IBEX_HOST" 'squeue --me -h | wc -l' # 0 = everything finished
When the queue drains, immediately classify with sacct — COMPLETED vs
FAILED vs PREEMPTED/TIMEOUT. An empty queue does not mean success.
- Retrieve results (create the local destination first — rsync does not create
a missing parent directory, and then exits 0 having copied nothing):
mkdir -p ./results && rsync -azP "$IBEX_HOST":<remote>/results/ ./results/ && ls ./results | wc -l
Incremental and safe to re-run; the trailing count is the check that files
actually arrived — never trust a clean exit alone (see deploy.md, "Transfer
commands").
- Analyze locally → adjust code/parameters → back to 1. Re-run only the
missing tasks using the idempotent submit pattern (slurm.md, "Idempotent
submit pattern") — that pattern is what makes the whole loop safely
re-entrant.
5. Key cluster facts (quick recall; details in references/)
- Scheduler: SLURM, reached over SSH from a login/frontend node.
- Ibex uses a single default
batch partition for CPU and GPU jobs alike;
you pick hardware via --gpus/--gres plus --constraint=<gpu-type>
(a100, v100, rtx2080ti, gtx1080ti, …), not via a GPU partition.
Wall-time cap is uniform (14 days). Constraint names and limits can drift —
verify live with sinfo -o "%P %l %D %c %m %G" and
sinfo -o "%n %G %f %t".
- Two login nodes:
ilogin (CPU) and glogin (GPU — use it when a build
needs to see a GPU, e.g. compiling CUDA code).
- Durable project storage lives under
/ibex/user/<username> (1.5 TB per
user, persists for the account's lifetime), distinct from the login home
directory (200 GB and a file-count quota — another reason conda envs
belong under /ibex/user) — do not conflate the two in scripts or project
memory.
- Off-campus access to Ibex typically requires the KAUST network or VPN;
if a connection that worked on campus fails off campus, that's the first
thing to check, not SSH key configuration.
- Ibex is only reachable this way if the user's local SSH client is correctly
routed (VPN / network) — that routing is local machine configuration, not
something this skill manages.
6. Off-campus / VPN access (knowledge, not an operation)
This section is background to explain when the user asks about connection
problems — it is not something this skill configures or performs on its own.
The skill always just uses $IBEX_HOST; whether that route needs KAUST's VPN
or a specific network is the user's local SSH client configuration, entirely
outside the skill's operational scope. Check current KAUST IT documentation
for the up-to-date VPN/SSH requirements, since these evolve independently of
this skill.
7. Reporting problems with this skill
This skill lives in the public repository https://github.com/Zhangyanbo/hpc-skills
(directory skills/kaust-ibex/) and is maintained from real usage: when
something in it turns out to be wrong or missing, that is worth an issue at
https://github.com/Zhangyanbo/hpc-skills/issues. Typical triggers, noticed while doing a task:
- a documented command failed or behaved differently from what the skill says
(wrong module name, flag, path, limit);
- a cluster fact here is stale (partition limits, quotas, hostnames, tool
versions);
- a gap that caused an avoidable detour — something you had to discover the
hard way that the skill should have said up front.
Procedure:
- Finish the user's task first; collect evidence as you go (the exact
command, its actual output / exit code, the skill file and section that
was wrong or silent).
- Draft the issue in English: title
kaust-ibex: <one-line symptom>; body with
which file/section, what the skill says, what actually happened,
cluster-side evidence, and a suggested fix. Concise and concrete.
- De-sensitize the text — the repository is public. No usernames /
username, ssh aliases, jump-host details, personal or lab paths: write
<username>, $IBEX_HOST, /ibex/user/<username>/... instead. Job IDs and version numbers
are fine.
- Show the draft to the user and file it only with their confirmation
(opening an issue is a public action):
gh issue create --repo Zhangyanbo/hpc-skills --title "<title>" --body-file <draft.md>
If gh is unavailable or the user prefers, hand them the draft to post
themselves.
Fixes are also welcome as pull requests (see the repository README).
1---2name: kaust-ibex3description: Operate the KAUST Ibex HPC cluster (SLURM) over SSH on the user's behalf: deploy code, submit / monitor / cancel jobs, manage GPU allocations (A100/V100), fetch results back, check quotas / partitions / GPU availability, and use the cluster as part of an iterate-loop. Use this skill whenever the user mentions running anything on Ibex / the HPC / cluster ("run this on ibex", "submit to slurm", "check my ibex jobs", "在 ibex 上跑"), asks about job status, storage quota, transferring files to/from the cluster, installing packages on the cluster, or anything involving sbatch / squeue / srun / sinfo / Ibex — even casually.4---56# KAUST Ibex HPC Operations78Deploy, submit, monitor, and retrieve results on Ibex (SLURM) over SSH, on the9user's behalf. **Top priority: never do anything that could violate cluster10policy or draw administrator attention** (see "Compliance red lines"). When in11doubt, take the slower, by-the-book path — the user's account is not worth any12shortcut.1314## 0. Preflight — run this before any Ibex work1516All connection details live on the local machine in `~/.config/kaust-ibex/config`17(shell syntax, `KEY=value`). **This skill contains no account information**; the18config file is the single source of truth. Start every Ibex session with:1920```bash21bash <this-skill-dir>/scripts/preflight.sh22```2324Branch on its output:2526- `READY host=... node=...` — connection works; proceed. `source` the config file27 to get:28 - `IBEX_HOST` — ssh target (an alias or `user@host`). Use it everywhere:29 `ssh "$IBEX_HOST" ...`, `rsync ... "$IBEX_HOST":...`30 - `IBEX_USER` — the user's KAUST login31 - `IBEX_PROJECT_ROOT` — durable project storage root, e.g.32 `/ibex/user/<username>` (a project's own remote path, if recorded in that33 project's CLAUDE.md, takes precedence)34- `NO_CONFIG` — first use on this machine; run "Guided setup" below.35- `NO_PASSWORDLESS` — key-based login is broken, or the KAUST network route is36 unreachable (Ibex login nodes are typically only reachable on the KAUST37 network or via VPN). **Stop all automated Ibex operations.** Tell the user:38 passwordless SSH is a prerequisite for automation — set up a key39 (`ssh-keygen` + `ssh-copy-id <host>`), confirm the KAUST VPN/network route is40 active, then retry. Never type passwords for the user or try to work around41 authentication.4243### Guided setup (only on NO_CONFIG)44451. Scan for candidates: `grep -B1 -A4 -i 'ibex.kaust.edu.sa' ~/.ssh/config`.462. If nothing is found or multiple candidates exist, ask the user which Host to47 use and what their KAUST login is. **Never guess account information.**483. Test passwordless login:49 `ssh -o BatchMode=yes -o ConnectTimeout=10 <host> 'echo OK && hostname'`.504. On success, write `~/.config/kaust-ibex/config` (template in the header of51 `scripts/preflight.sh`) and `chmod 600` it. Also probe for the durable52 project root: `ssh <host> 'ls -d /ibex/user/$USER 2>/dev/null'` and record53 it in `IBEX_PROJECT_ROOT` if present.545. On failure, follow NO_PASSWORDLESS above; do not write55 `IBEX_PASSWORDLESS=yes`.5657## 1. Compliance red lines (each one is a hard constraint)58591. **Login/frontend nodes are for light operations only**: ls / cat / squeue /60 sbatch / editing small files / small scp. Anything that burns CPU, memory,61 or heavy IO — installing packages, building conda/mamba environments,62 extracting large archives, bulk-deleting big directories, data processing,63 running any program — **must go through a compute node**, either an64 interactive allocation (`salloc`/`srun --pty`) or a batch job (`sbatch`).652. **Every Ibex action must trace back to an explicit user request.** Once the66 user says "run X on Ibex", the deploy → submit → monitor → retrieve chain67 for that task can run autonomously; actions outside that scope (touching68 other directories, cancelling unrelated jobs) are off-limits.693. **Destructive operations require a confirmed list first**: bulk `rm`,70 overwriting existing remote results, `scancel` on jobs not submitted in71 this task, killing a persistent interactive/dev-server allocation another72 task may still need.734. **Rate-limit polling**: status-check loops at ≥ 60-second intervals (don't74 hammer `squeue`). Batch several remote commands into one ssh call75 (`ssh host 'cmd1; cmd2; cmd3'`) — fewer connections, lower latency.765. **Stay well below quota ceilings.** Check current storage usage77 (`df -h /ibex/user` or the cluster's quota command) before large writes —78 `/ibex/user` can run close to full, and a full filesystem blocks writes for79 every user sharing it, not just the current job.806. **No restricted data on the cluster.** Never store or enter passwords/API81 keys on the user's behalf — those belong in a project `.env`. Treat any82 logs from persistent dev-server-style jobs (e.g. remote IDE servers) as83 potentially sensitive if they can embed a generated access token/password.8485## 2. Status checks (when the user asks "how are my jobs doing?")8687Grab everything in one ssh call:8889```bash90ssh "$IBEX_HOST" 'squeue --me; echo ---; sacct -X --starttime today -o JobID,JobName%20,State,Elapsed,ExitCode | tail -30'91```9293| To see | Command (inside ssh) |94|---|---|95| Running / queued jobs | `squeue --me` |96| Recent job outcomes (incl. failures) | `sacct -X --starttime <date> -o JobID,JobName%20,State,Elapsed,ExitCode` |97| Resource efficiency of a finished job | `seff <jobid>` |98| Storage usage | `df -h /ibex/user` (or the cluster's official quota command) |99| Partition / node states | `sinfo` |100| GPU availability | `sinfo -o "%n %G %f %t"` (single `batch` partition; filter by feature/GRES) |101| Job logs | `tail -50 <submit-dir>/slurm-<jobid>.out` (or the path set via `--output`) |102| Recover a job's real account/QOS/paths | `scontrol show job <id>` |103104Failure triage order: tail of the `.err` file → `sacct` State/ExitCode (`OOM` →105more memory, `TIMEOUT` → more time, `NODE_FAIL`/`PREEMPTED` → just resubmit) →106`seff` to see whether resources were undersized.107108## 3. Task routing109110- **Deploying code / transferring files / setting up environments (conda, uv) /111 storage & quota issues** → read [references/deploy.md](references/deploy.md) first.112- **Writing SLURM scripts / submitting jobs / GPU-type-aware requests / debugging113 jobs / interactive & persistent-dev-server sessions** → read114 [references/slurm.md](references/slurm.md) first.115- Both at once (the common "run X on Ibex") → read both, execute in116 deploy → slurm order.117- **Something in this skill turned out wrong or missing, or the user says118 "file that as an issue"** → §7 (draft an issue for the skill's repository;119 file only after the user confirms).120121## 4. Using Ibex inside a loop (submit → wait → retrieve → iterate)122123Standard loop skeleton:1241251. Deploy changed files (full dependency-chain check, see deploy.md), then126 submit (see slurm.md).1272. Wait in the background, polling at ≥ 60s intervals (scale up to 5–10128 minutes for long jobs):129 ```bash130 ssh "$IBEX_HOST" 'squeue --me -h | wc -l' # 0 = everything finished131 ```132 When the queue drains, immediately classify with `sacct` — COMPLETED vs133 FAILED vs PREEMPTED/TIMEOUT. An empty queue does not mean success.1343. Retrieve results (create the local destination first — rsync does not create135 a missing parent directory, and then exits 0 having copied nothing):136 ```bash137 mkdir -p ./results && rsync -azP "$IBEX_HOST":<remote>/results/ ./results/ && ls ./results | wc -l138 ```139 Incremental and safe to re-run; the trailing count is the check that files140 actually arrived — never trust a clean exit alone (see deploy.md, "Transfer141 commands").1424. Analyze locally → adjust code/parameters → back to 1. Re-run only the143 missing tasks using the idempotent submit pattern (slurm.md, "Idempotent144 submit pattern") — that pattern is what makes the whole loop safely145 re-entrant.146147## 5. Key cluster facts (quick recall; details in references/)148149- Scheduler: SLURM, reached over SSH from a login/frontend node.150- Ibex uses a **single default `batch` partition** for CPU and GPU jobs alike;151 you pick hardware via `--gpus`/`--gres` plus `--constraint=<gpu-type>`152 (`a100`, `v100`, `rtx2080ti`, `gtx1080ti`, …), not via a GPU partition.153 Wall-time cap is uniform (14 days). Constraint names and limits can drift —154 verify live with `sinfo -o "%P %l %D %c %m %G"` and155 `sinfo -o "%n %G %f %t"`.156- Two login nodes: `ilogin` (CPU) and `glogin` (GPU — use it when a build157 needs to see a GPU, e.g. compiling CUDA code).158- Durable project storage lives under `/ibex/user/<username>` (1.5 TB per159 user, persists for the account's lifetime), distinct from the login home160 directory (200 GB **and a file-count quota** — another reason conda envs161 belong under `/ibex/user`) — do not conflate the two in scripts or project162 memory.163- Off-campus access to Ibex typically requires the KAUST network or VPN;164 if a connection that worked on campus fails off campus, that's the first165 thing to check, not SSH key configuration.166- Ibex is only reachable this way if the user's local SSH client is correctly167 routed (VPN / network) — that routing is local machine configuration, not168 something this skill manages.169170## 6. Off-campus / VPN access (knowledge, not an operation)171172This section is background to *explain* when the user asks about connection173problems — it is not something this skill configures or performs on its own.174The skill always just uses `$IBEX_HOST`; whether that route needs KAUST's VPN175or a specific network is the user's local SSH client configuration, entirely176outside the skill's operational scope. Check current KAUST IT documentation177for the up-to-date VPN/SSH requirements, since these evolve independently of178this skill.179180## 7. Reporting problems with this skill181182This skill lives in the public repository <https://github.com/Zhangyanbo/hpc-skills>183(directory `skills/kaust-ibex/`) and is maintained from real usage: when184something in it turns out to be wrong or missing, that is worth an issue at185<https://github.com/Zhangyanbo/hpc-skills/issues>. Typical triggers, noticed while doing a task:186187- a documented command failed or behaved differently from what the skill says188 (wrong module name, flag, path, limit);189- a cluster fact here is stale (partition limits, quotas, hostnames, tool190 versions);191- a gap that caused an avoidable detour — something you had to discover the192 hard way that the skill should have said up front.193194Procedure:1951961. Finish the user's task first; collect evidence as you go (the exact197 command, its actual output / exit code, the skill file and section that198 was wrong or silent).1992. Draft the issue in English: title `kaust-ibex: <one-line symptom>`; body with200 which file/section, what the skill says, what actually happened,201 cluster-side evidence, and a suggested fix. Concise and concrete.2023. **De-sensitize the text — the repository is public.** No usernames /203 username, ssh aliases, jump-host details, personal or lab paths: write204 `<username>`, `$IBEX_HOST`, `/ibex/user/<username>/...` instead. Job IDs and version numbers205 are fine.2064. **Show the draft to the user and file it only with their confirmation**207 (opening an issue is a public action):208 ```bash209 gh issue create --repo Zhangyanbo/hpc-skills --title "<title>" --body-file <draft.md>210 ```211 If `gh` is unavailable or the user prefers, hand them the draft to post212 themselves.213214Fixes are also welcome as pull requests (see the repository README).