> For the complete documentation index, see [llms.txt](https://igb.mit.edu/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://igb.mit.edu/mini-courses/research-computing-on-engaging-with-vscode/vscode/llm-support.md).

# LLM Support

## VSCode Extensions

VSCode has built-in support for using CoPilot to create and edit files, among other VSCode features. If you pay for CoPilot, you can login to your account to use CoPilot from the "Chat" side window.

For users of Anthropic's Claude, Anthropic has their own VSCode extension. Navigate to the Extensions window from the left sidebar, and search "Claude." Make sure to install the verified extension from Anthropic.&#x20;

<figure><img src="https://498238201-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FWuHhstIreJ3jFvE4gQ3y%2Fuploads%2FxfokiF8VK86axwHLFy4b%2FScreenshot%202026-09-23%20at%203.13.03%E2%80%AFPM.png?alt=media&amp;token=f60e105a-bcd1-4458-833d-81ec970e2796" alt=""><figcaption></figcaption></figure>

After the extension has been installed, you can navigate to the Claude Code window by clicking the sidebar button on the top-right, then switching to the "Claude Code" tab. You can now input instructions into the text box. You will be prompted to login to your Claude account.

<figure><img src="https://498238201-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FWuHhstIreJ3jFvE4gQ3y%2Fuploads%2FQuVSifQFC0J6Q6Y2jcbl%2FScreenshot%202026-09-23%20at%203.17.33%E2%80%AFPM.png?alt=media&amp;token=2aff4fe6-5046-4960-9c0d-8b849a795441" alt=""><figcaption></figcaption></figure>

After logging in, you can begin sending instructions to Claude. For example, here I have input "Create a new file named "README.md" that includes basic examples for using apptainer." The opened "README.md" file is the one output by Claude.

<figure><img src="https://498238201-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FWuHhstIreJ3jFvE4gQ3y%2Fuploads%2FZugGEu8RcPWKQfq18p7i%2FScreenshot%202026-09-23%20at%203.25.01%E2%80%AFPM.png?alt=media&amp;token=16db1e25-a220-4db2-b718-5b153709f9b7" alt=""><figcaption></figcaption></figure>

## Sandboxing LLMs

While LLMs can be useful, giving them unfettered access to your files can be dangerous. There have been documented cases of LLMs executing commands that delete people's folder containing all of their projects. To avoid this issue, you should run an LLM inside of a sandbox and scope its access to only the directories where you are doing work.

Below is a script that will create such a sandbox on your behalf. Simply copy the contents of this script to `~/.local/bin/claude-sandbox` , then make it executable by running `chmod +x ~/.local/bin/claude-sandbox` .

```bash
#!/usr/bin/bash

set -uo pipefail

BWRAP_TEMP_FILES="/tmp/$USER/bwrap-files"

# Flattened bwrap arguments for user-requested dirs: (--bind SRC DEST ...)
EXTRA_BINDS=()
# Resolved paths already queued, used for de-duplication
SEEN_PATHS=()
POSITIONAL=()

usage() {
    cat <<EOF
Usage: ${0##*/} [OPTIONS] [WORKSPACE_DIR]

Options:
  -b, --bind DIR[,DIR...]      Bind extra directory into the sandbox read-write
  -r, --ro-bind DIR[,DIR...]   Bind extra directory into the sandbox read-only
  -h, --help                   Show this help and exit

  * Both options may be repeated and accept comma-separated lists.
  * A ':ro' or ':rw' suffix on an individual path overrides the flag's mode.
  * Paths are mounted at the same location inside the sandbox as on the host.
  * The SANDBOX_EXTRA_DIRS environment variable is parsed the same way as -b.

Examples:
  ${0##*/} -b /nfs/mylab/data ~/projects/myapp
  ${0##*/} -b /nfs/mylab/data -r /orcd/software/extra
  ${0##*/} -b '/nfs/mylab/data,/scratch/cache:ro'
  SANDBOX_EXTRA_DIRS=/nfs/mylab/data:ro ${0##*/}
EOF
}

# add_bind <default-mode> <path-spec>
add_bind() {
    local mode="$1" spec="$2" resolved seen

    case "$spec" in
        *:ro) mode="--ro-bind" ; spec="${spec%:ro}" ;;
        *:rw) mode="--bind"    ; spec="${spec%:rw}" ;;
    esac

    [ -n "$spec" ] || return 0

    if ! resolved="$(realpath -e -- "$spec" 2>/dev/null)"; then
        echo "Warning: '$spec' does not exist on the host; not binding it." >&2
        return 0
    fi

    if [ ! -r "$resolved" ]; then
        echo "Warning: '$resolved' is not readable by you; not binding it." >&2
        return 0
    fi

    # Never let a user hand the whole filesystem or their home dir to the sandbox
    case "$resolved" in
        / | "$HOME")
            echo "Refusing to bind '$resolved' into the sandbox. Skipping." >&2
            return 0
            ;;
    esac

    for seen in ${SEEN_PATHS[@]+"${SEEN_PATHS[@]}"}; do
        [ "$seen" == "$resolved" ] && return 0
    done

    SEEN_PATHS+=("$resolved")
    EXTRA_BINDS+=("$mode" "$resolved" "$resolved")
}

# add_bind_list <default-mode> <comma-separated-specs>
add_bind_list() {
    local mode="$1" list="$2" item
    local -a items=()

    IFS=',' read -r -a items <<< "$list"
    for item in ${items[@]+"${items[@]}"}; do
        add_bind "$mode" "$item"
    done
}

# ---------------------------------------------------------------- argument parsing
while [ $# -gt 0 ]; do
    case "$1" in
        -b|--bind|-r|--ro-bind)
            if [ $# -lt 2 ]; then
                echo "Error: $1 requires a directory argument." >&2
                exit 1
            fi
            case "$1" in
                -b|--bind) add_bind_list "--bind" "$2" ;;
                *)         add_bind_list "--ro-bind" "$2" ;;
            esac
            shift 2
            ;;
        --bind=*)    add_bind_list "--bind"    "${1#*=}" ; shift ;;
        --ro-bind=*) add_bind_list "--ro-bind" "${1#*=}" ; shift ;;
        -h|--help)   usage ; exit 0 ;;
        --)          shift ; POSITIONAL+=("$@") ; break ;;
        -*)          echo "Error: unknown option '$1'. Try --help." >&2 ; exit 1 ;;
        *)           POSITIONAL+=("$1") ; shift ;;
    esac
done

# Extra dirs from the environment (handy for wrapper scripts / module files)
if [ -n "${SANDBOX_EXTRA_DIRS:-}" ]; then
    add_bind_list "--bind" "$SANDBOX_EXTRA_DIRS"
fi

if [ "${#POSITIONAL[@]}" -gt 1 ]; then
    echo "Error: expected at most one workspace directory, got ${#POSITIONAL[@]}." >&2
    exit 1
fi

USER_SUPPLIED_DIR="${POSITIONAL[0]:-}"
if [ -n "$USER_SUPPLIED_DIR" ]; then
    if [ ! -d "$USER_SUPPLIED_DIR" ]; then
        echo "Workspace '$USER_SUPPLIED_DIR' does not exist or is not a directory. Exiting."
        exit 1
    fi
    WORKSPACE_DIR="$(realpath -e -- "$USER_SUPPLIED_DIR")"
else
    WORKSPACE_DIR="$PWD"
fi

# ---------------------------------------------------------------- sanity checks
if ! command -v claude &> /dev/null; then
    echo 'The `claude` command line tool is not installed. Install by following the instructions here: https://code.claude.com/docs/en/quickstart'
    exit 1
	fi

CLAUDE_BIN_PATH=$(dirname $(realpath $(which claude)))

if [ "$WORKSPACE_DIR" == "$HOME" ]; then
    echo "Refusing to use $HOME, your home directory, as a workspace. Exiting."
    exit 1
fi

echo "Creating sandbox in $WORKSPACE_DIR"
if [ "${#SEEN_PATHS[@]}" -gt 0 ]; then
    for i in "${!SEEN_PATHS[@]}"; do
        mode="${EXTRA_BINDS[$((i * 3))]}"
        [ "$mode" == "--ro-bind" ] && mode="read-only" || mode="read-write"
        echo "  extra mount: ${SEEN_PATHS[$i]} ($mode)"
    done
fi

mkdir -p $BWRAP_TEMP_FILES
getent passwd $(id -u) > "$BWRAP_TEMP_FILES/passwd"
getent group $(id -g) > "$BWRAP_TEMP_FILES/group"

exec /usr/bin/bwrap \
    --tmpfs /tmp \
    --dev /dev \
    --dev-bind /dev/fuse /dev/fuse \
    --proc /proc \
    --unshare-uts \
    --hostname bubblewrap \
    --ro-bind /sys /sys \
    --ro-bind /bin /bin \
    --ro-bind /lib /lib \
    --ro-bind /usr/lib64 /usr/lib64 \
    --ro-bind /lib64 /lib64 \
    --ro-bind /usr/bin /usr/bin \
    --ro-bind /usr/lib /usr/lib \
    --ro-bind /usr/libexec /usr/libexec \
    --ro-bind /usr/local/bin /usr/local/bin \
    --ro-bind /usr/local/lib /usr/local/lib \
    --ro-bind /etc/alternatives /etc/alternatives \
    --ro-bind /etc/resolv.conf /etc/resolv.conf \
    --ro-bind /etc/profile.d /etc/profile.d \
    --ro-bind /etc/bash_completion.d /etc/bash_completion.d \
    --ro-bind /etc/bashrc /etc/bashrc \
    --ro-bind /etc/ssl/certs /etc/ssl/certs \
    --ro-bind /etc/pki /etc/pki \
    --ro-bind /etc/ld.so.cache /etc/ld.so.cache \
    --ro-bind /etc/ld.so.conf /etc/ld.so.conf \
    --ro-bind /etc/ld.so.conf.d /etc/ld.so.conf.d \
    --ro-bind /etc/localtime /etc/localtime \
    --ro-bind /etc/nsswitch.conf /etc/nsswitch.conf \
    --ro-bind /etc/hosts /etc/hosts \
    --ro-bind /orcd/software /orcd/software \
    --ro-bind /usr/share /usr/share \
    --ro-bind /var/tmp /var/tmp \
    --ro-bind /nfs /nfs \
    --ro-bind "$HOME/.bashrc" "$HOME/.bashrc" \
    --ro-bind "$HOME/.bash_profile" "$HOME/.bash_profile" \
    --ro-bind "$HOME/.local" "$HOME/.local" \
    --ro-bind "$HOME/.conda" "$HOME/.conda" \
    --ro-bind "$BWRAP_TEMP_FILES/passwd" /etc/passwd \
    --ro-bind "$BWRAP_TEMP_FILES/group" /etc/group \
    --bind "$HOME/.cache" "$HOME/.cache" \
    --bind "$HOME/.claude" "$HOME/.claude" \
    --bind "$HOME/.claude.json" "$HOME/.claude.json" \
    --bind "$HOME/.local/state/claude" "$HOME/.local/state/claude" \
    --bind "$CLAUDE_BIN_PATH" "$CLAUDE_BIN_PATH" \
    ${EXTRA_BINDS[@]+"${EXTRA_BINDS[@]}"} \
    --bind "$WORKSPACE_DIR" "$WORKSPACE_DIR" \
    --chdir "$WORKSPACE_DIR" \
    claude

```

To use `claude-sandbox`, you must first install the Claude Code tool. Please follow [these instructions](https://code.claude.com/docs/en/quickstart#step-1-install-claude-code) to do so.

You can run `claude-sandbox --help` to get a description for how to use this tool.

```bash
[asoberan@login010 ~]$ claude-sandbox --help
# Usage: claude-sandbox [OPTIONS] [WORKSPACE_DIR]
# 
# Options:
#   -b, --bind DIR[,DIR...]      Bind extra directory into the sandbox read-write
#   -r, --ro-bind DIR[,DIR...]   Bind extra directory into the sandbox read-only
#   -h, --help                   Show this help and exit
# 
#   * Both options may be repeated and accept comma-separated lists.
#   * A ':ro' or ':rw' suffix on an individual path overrides the flag's mode.
#   * Paths are mounted at the same location inside the sandbox as on the host.
#   * The SANDBOX_EXTRA_DIRS environment variable is parsed the same way as -b.
# 
# Examples:
#   claude-sandbox -b /nfs/mylab/data ~/projects/myapp
#   claude-sandbox -b /nfs/mylab/data -r /orcd/software/extra
#   claude-sandbox -b '/nfs/mylab/data,/scratch/cache:ro'
#   SANDBOX_EXTRA_DIRS=/nfs/mylab/data:ro claude-sandbox
```

Running `claude-sandbox` with no arguments will create a sandbox in whatever directory you are currently in, so that Claude will only have access to the contents of that specific directory.

Running `claude-sandbox /an/example/path` will create the sandbox at whatever directory you specified.

`claude-sandbox` will not allow you to create a sandbox in your home directory, as that would effectively make the sandbox useless for protecting your files.

You can bind extra directories into the sandbox by passing paths as arguments to `--bind` or `--ro-bind`. For example, if there is a reference genome in a separate directory from your project folder that you want to access inside the sandbox, you'd pass the path to that genome to these flags.

Directories passed to `--bind` will be readable and writable in the sandbox. Directories passed to `--ro-bind` will only be readable.

Below is an example of the sandbox in action. The sandbox is created in `/home/asoberan/projects/training/sandbox`. The directory above this contains a couple of files: `README.md` and `notes.txt`.

```bash
[asoberan@login010 sandbox]$ pwd
/home/asoberan/projects/training/sandbox
[asoberan@login010 sandbox]$ ls
example_file.txt
[asoberan@login010 sandbox]$ ls ..
README.md  notes.txt  sandbox
[asoberan@login010 sandbox]$ claude-sandbox
Creating sandbox in /home/asoberan/projects/training/sandbox
```

However, Claude Code has no visibility to those files.

```
 ▐▛███▛█   Claude Code v2.1.273
▝▜██████▀  Sonnet 5 · Claude Pro
  ▝▝ ▝▝    ~/projects/training/sandbox


❯ What files are in the parent directory?

  Listed 1 directory

● The parent directory (/home/asoberan/projects/training) only contains one item: the sandbox directory itself — no other files.

✻ Brewed for 4s · done 10:34 AM
```

{% hint style="warning" %}
This sandboxing script is experimental and will likely change as more users test it. If you run into any problems while using this script, please email <asoberan@mit.edu>.
{% endhint %}

### Sandboxed LLMs in VSCode

Unfortunately, I was unable to get the Claude Code VSCode extension to connect to a sandboxed Claude running a remote control session. It's still possible to control this remote session from Claude Desktop, your web browser, the Claude app on your phone, or from another Claude Code session, but not from the VSCode Claude Code chat window.

If a workaround is found to this problem, this documentation will be updated with the fix. Until then, use of a sandboxed Claude can be achieved in VSCode the following way.

First, I recommend moving the Terminal tab to the secondary side bar on the right. Do this by **right-clicking** **Terminal > Move To > Secondary Side Bar**.

<figure><img src="https://498238201-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FWuHhstIreJ3jFvE4gQ3y%2Fuploads%2F4kjNUuzaRdCZqKxgH5nX%2FScreenshot%202026-09-24%20at%2010.44.57%E2%80%AFAM.png?alt=media&amp;token=e059a96f-d646-4ce9-b268-b98ff70abd26" alt=""><figcaption></figcaption></figure>

Once the Terminal has moved, you'll see it on the right side bar. In this Terminal window, you can run `claude-sandbox` in the directory of your choice. In the example below, I'm running the sandbox in the `sandbox` directory which contains `example_file.txt`.

<figure><img src="https://498238201-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FWuHhstIreJ3jFvE4gQ3y%2Fuploads%2FhgFphRbc9YDOB8zExI6o%2FScreenshot%202026-09-24%20at%2010.46.29%E2%80%AFAM.png?alt=media&amp;token=6d01aaf1-cd69-435f-9191-88f6a2d79516" alt=""><figcaption></figcaption></figure>

The sandboxed Claude Code will now run on the right side bar, mirroring the experience of the official Claude Code VSCode extension. Input instructions as you see fit. Any changes to files will be mirrored in your VSCode window.&#x20;

<figure><img src="https://498238201-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FWuHhstIreJ3jFvE4gQ3y%2Fuploads%2FBkrqc8FfGEAdi5MPWFLr%2FScreenshot%202026-09-24%20at%2010.47.38%E2%80%AFAM.png?alt=media&amp;token=822d98de-343f-4eeb-b995-1eaf17756d43" alt=""><figcaption><p>That is not Kermit...</p></figcaption></figure>
