Skip to main content
ClaudeWave
Skill1.6k repo starsupdated 4d ago

modal-run

Use when the user asks to run heavy or GPU work on Modal (the cloud compute platform) — writing a Modal function in the workspace, running it with the user's own `modal` CLI + token, and bringing results back. Data-to-compute for jobs too big for the laptop, without a Slurm cluster.

Install in Claude Code
Copy
git clone --depth 1 https://github.com/ai4s-research/open-science /tmp/modal-run && cp -r /tmp/modal-run/runtime/skills/core/modal-run ~/.claude/skills/modal-run
Then start a new Claude Code session; the skill loads automatically.

SKILL.md

# Run compute on Modal

Modal runs code in the cloud on demand (CPU/GPU), billed to the **user's own**
Modal account. Like the HPC/Slurm path, the app never handles credentials — you
use the user's installed `modal` CLI and their token. Prefer local execution or
Slurm first; reach for Modal when the job needs cloud GPUs or elastic scale and
no cluster is available.

## 1 · Check Modal is ready

Modal must be installed and authenticated (the Settings **Cloud compute (Modal)**
card shows this). Verify before writing code:

```bash
modal --version          # installed?
test -f ~/.modal.toml && echo "authenticated" || echo "run: modal token new"
```

If it is not installed, tell the user to `pip install modal`; if not
authenticated, ask them to run `modal token new` in their terminal (it opens a
browser). Do **not** attempt to create or store tokens yourself.

## 2 · Write the Modal function into the workspace

Put the script in the workspace so provenance records it. Pin dependencies in
the image so the run is reproducible, and fix any random seed.

```python
# compute.py — run with:  modal run compute.py
import modal

app = modal.App("open-science-job")
image = modal.Image.debian_slim().pip_install("numpy==1.26.4", "scipy==1.13.1")

@app.function(image=image, gpu=None, timeout=1800)  # set gpu="A10G" etc. if needed
def run(n: int = 1_000_000):
    import numpy as np
    rng = np.random.default_rng(0)          # fixed seed → reproducible
    x = rng.standard_normal(n)
    return {"n": n, "mean": float(x.mean()), "std": float(x.std())}

@app.local_entrypoint()
def main():
    result = run.remote()
    print(result)                            # printed locally; capture it below
```

## 3 · Run it and capture the result

`modal run` executes remotely and streams logs + the local entrypoint's stdout
back. Write the result into a fresh, immutable result directory so it becomes a
traceable artifact and does not overwrite a previous run:

```bash
RESULT=results/<job-name>/<YYYYmmdd-HHMMSS>
mkdir -p "$RESULT"
modal run compute.py | tee "$RESULT"/modal_result.txt
```

For large outputs, have the function write to a Modal Volume and download with
`modal volume get`, rather than returning big objects. Download every run into
its own `RESULT` directory; never reuse a recorded output path.

## 4 · Record the run (reproducibility) — REQUIRED, every time

Modal runs on remote cloud hardware the app can't see, so this call is the ONLY
thing that makes the run exist in Runs. Do it after **every** completed run —
including quick re-runs. Skipping it loses the run entirely (it shows in neither
the global Runs view nor the session). Record it after it completes (from the
workspace root):

Record it completely: `--code` once per script that ran, and `--output` once
per file you captured or downloaded (the streamed result **and** any
`modal volume get` files) — not just the summary. Output paths must be under the
fresh `RESULT` directory; the helper refuses to record paths used by earlier
runs.

```bash
python "$XDG_CONFIG_HOME/opencode/skills/modal-run/record_run.py" \
  --surface modal --command "modal run compute.py" \
  --status <ok|failed> --host "modal:<app-name>" \
  --hardware "<the gpu= from @app.function, e.g. A10G — or 'CPU'>" \
  --code compute.py --output "$RESULT"/modal_result.txt \
  --output "$RESULT"/<each downloaded file> \
  --session-id "$(cat .openscience/session.txt 2>/dev/null)"
```

`--session-id` attaches the run to this session (empty-safe if the marker's absent).

The environment is reproduced by the `modal.Image` definition in `compute.py`
(pinned `pip_install` + base image — already versioned in the workspace), so
record the GPU/hardware string, not a package list, and no `--env-file` is
needed. Use `--status failed` if the run errored.

## Rules

- **User's account only.** Never handle, print, or store Modal tokens.
- **Reproducible.** Pin image packages and fix seeds; record the script + result
  in the workspace (provenance captures them).
- **Cost-aware.** Modal bills the user — keep `timeout` bounded, don't request a
  GPU unless the work needs one, and say what you're about to run before a large
  job.
my-skillSkill

A test skill that says hello. Use when you want to test skill loading or verify that the skill system is working.

verifySkill

Verify apps/desktop frontend changes visually without launching the Tauri app or a live model

domain-checkSkill

Use whenever you write or run scientific analysis code (physics, earth/geo, biology, chemistry, or social science) in this workspace — before executing it and again after generating results. Runs a deterministic domain-correctness gate that catches code which runs but is scientifically wrong (unit/dimension mismatch, Euclidean distance on lat/lon without a CRS, 0-based/1-based coordinate and strand errors, impossible SMILES valence, uncorrected multiple comparisons, averaging a categorical code). Surfaces structured findings; never claims the code is correct.

large-fileSkill

Use BEFORE reading any data file that could be large (CSV/TSV, Parquet, HDF5, FITS, NetCDF, NDJSON, genomics FASTQ/FASTA/VCF/BAM, GRIB, ROOT, or big text/simulation logs like VASP OUTCAR). Returns a compact memory pointer — header/schema/shape/sample/key numbers — by introspection and sampling in bounded memory, so you never load a file bigger than the context window into the model. Reference data via the pointer; read specific ranges deterministically.

publication-figuresSkill

Use whenever you generate or review a chart, plot, table, or paper figure in this workspace, including work delegated by paper-writing, literature-survey, and experiment skills. Applies the Open Science publication style, enforces readable final-size layout for figures and tables, and rejects generic diagram-tool output as a publication figure. Interactive Plotly/HTML may be used for exploration, but paper delivery requires a static publication-ready export.

remote-computeSkill

Use when the user asks to run, submit, monitor, or cancel a job on a remote machine over SSH — their own GPU/CPU server, a workstation, or a Slurm cluster ("the cluster", a login node, "my 3090 box", "the compute server"). Picks a saved machine, runs the work directly over SSH (or via Slurm when present), tracks it, and fetches results back into the workspace.

stats-integritySkill

Use whenever you run statistical analysis for the social sciences (regression, hypothesis tests, econometrics) or read Stata (.dta) / SPSS (.sav) data in this workspace. Enforces an execute-don't-interpret boundary (surface estimates, don't volunteer causal claims), checks the analysis against a preregistration plan for HARKing, verifies reproducible seeds, and reproduces .dta/.sav estimates via R. Flags integrity risks; never certifies the analysis is sound.

traceability-reviewSkill

Use when the user asks to review, verify, or audit a report, manuscript, or analysis in the workspace for traceability — resolving citations, flagging numbers with no source, and checking figures against the code that generated them. Emits a structured review block the app renders as reviewer findings. Verifies traceability, never "correctness".