# 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.](/sandboxes/lifecycle-scripts.md)
{% 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](/tracks/challenges/skipping-challenges.md). 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](/tracks/manage/test-a-track.md).

#### 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 %}


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.instruqt.com/sandboxes/lifecycle-scripts/add-a-script-to-check-challenge-execution.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
