# Challenge scripts

## Overview

Challenge scripts can be written in whatever scripting language you like, such as Bash or Python. There are four types of challenge scripts:

* *Setup*: Automate commands prior to the challenge starting
* *Check*: Determine if users completed specific tasks, runs when **Check** is clicked
* *Solve*: Automate users work, runs when **Skip** is clicked
* *Cleanup*: Automate commands once a challenge is completed

{% hint style="info" %}
[Read more about lifecycle scripts and see examples.](https://docs.instruqt.com/sandboxes/lifecycle-scripts)
{% endhint %}

## Add challenge scripts

Challenge scripts can be added using the Web UI or the Instruqt CLI.

{% tabs %}
{% tab title="🌐 Web UI" %}

1. From a *Track dashboard* page, click the challenge you wish to add a script to.
2. From the top navigation bar, click **Scripts**.
3. Determine which host in the sandbox you want the script to run on.
4. Add a script to the host's `setup`, `check`, `solve`, or `cleanup` script file.
   {% endtab %}

{% tab title="💻 Instruqt CLI" %}

1. Within a challenge directory, challenge scripts are defined in a `<type>-<hostname>` format. For example, to add a check script that runs on a host named `webserver`, you must create a file named `check-webserver` into the challenge directory. The other types are `setup`, `solve`, and `cleanup`.&#x20;
   {% endtab %}
   {% endtabs %}

### Setup scripts

Use challenge setup scripts to:

* Create files that are necessary for the challenge.
* Send analytics events.

#### Example

The following example creates an empty file and a pre-filled file that are available in a challenge:

{% tabs %}
{% tab title="Bash" %}

```bash
#!/bin/bash 
set -euxo pipefail

# create an empty file called challenge.txt
echo > challenge.txt

# create a pre-filled file called readme.md
echo " # How to create a challenge setup script  " > readme.md
```

{% endtab %}
{% endtabs %}

### Check scripts

Use challenge check scripts to:

* Check if a learner solved a challenge correctly.
* Provide a fail message and a hint if the learner failed to solve the challenge.

#### Example

The following example checks if the learner created a directory called `instruqt`. If the learner created the directory, the script returns a success message, and Instruqt continues with the next challenge. If the learner has not created the directory, the script returns a fail message with a hint to the learner, and Instruqt stays at the current challenge.

{% tabs %}
{% tab title="Bash" %}

```bash
#!/bin/bash
set -euxo pipefail

echo "Checking if the directory instruqt exists."

if [ -d /root/instruqt ]
then
    echo "The directory instruqt exists"
else
    fail-message "There is no directory named instruqt, did you create it?"
fi
```

{% endtab %}
{% endtabs %}

Alternatively, the following example uses an exit code to process the challenge check. If the check fails, line 5 sends a feedback message prefixed with `FAIL:` to the `stdout` and line 6 sets the exit code to `1`, which marks the script as unsuccessful:

{% tabs %}
{% tab title="Bash" %}

```bash
#!/bin/bash

echo "Checking the solution of the challenge"
if [ !$EVERYTHING_WENT_WELL ]; then
  echo "FAIL: Your challenge failed because of [REASON]"
  exit 1
fi
```

{% endtab %}
{% endtabs %}

### Solve scripts

A challenge solve script solves the current challenge to allow the learner to skip ahead if you [enabled skipping](https://docs.instruqt.com/tracks/challenges/skipping-challenges). Challenge solve scripts run in the following scenarios:

* When a learner skips a challenge.
* When you issue the `instruqt track test`  command in Instruqt CLI to [test a track](https://docs.instruqt.com/tracks/manage/test-a-track).

#### Example

The following example solves a challenge by creating a directory called `instruqt`:

{% tabs %}
{% tab title="Bash" %}

```bash
#!/bin/bash
set -euxo pipefail

mkdir -p /root/instruqt
```

{% endtab %}
{% endtabs %}

### Cleanup scripts

{% hint style="info" %}
Cleanup scripts run asynchronously, and the track will continue to be run while the script is running.

For resetting or setting up state for the next challenge, use [#setup-scripts](#setup-scripts "mention").
{% endhint %}

A challenge cleanup script runs asynchronously after the learner completes a challenge.

Use challenge cleanup scripts to remove artefacts that are no longer used for the rest of the track early.

#### Example

The following example resets an earlier file that the learner changed:

{% tabs %}
{% tab title="Bash" %}

```bash
#!/bin/bash 
set -euxo pipefail

# overwrite with an empty file 
echo > challenge.txt
```

{% endtab %}
{% endtabs %}
