> ## Documentation Index
> Fetch the complete documentation index at: https://3to1go.docs.thesteau.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Edge hooks

> Run your own commands before and after Edge processes each backup job.

Hooks let Edge run a shell command around each job in a backup cycle:

* **Pre command**: before Edge scans and archives the job. Edge waits for it to finish. Useful for dumping a database into the folder first.
* **Post command**: after the job is done, whether it uploaded, was unchanged, or failed. Cancellation skips the post command.

Hooks run during scheduled cycles and **Run Backup Cycle Now**. The individual **Force Upload** action currently bypasses both hooks.

## Set up

<Steps>
  <Step title="Open Custom Scripts">
    In Edge, click **Custom Scripts**.
  </Step>

  <Step title="Upload a script (optional)">
    Under **Uploaded Items**, upload up to **3** files. Only `.sh` scripts and `.txt` helper files are allowed, and they must be UTF-8 text. `.sh` files are made executable, and Windows line endings are converted.
  </Step>

  <Step title="Set the commands">
    Enter a **Pre Command** and/or **Post Command**. Either:

    * the name of an uploaded script, such as `before-backup.sh`, or
    * any shell command, such as `curl -fsS https://hc-ping.com/your-id`.
  </Step>
</Steps>

Commands run with `sh -c` inside the Edge container, from the hook scripts folder (`/hook-scripts`). Each command has a **5-minute** timeout, and is stopped if you **Cancel operation**. Output and non-zero exit codes go to Edge's logs; a failing hook doesn't stop the backup.

The same commands run for **every** job. Use `THREETOONEGO_JOB_NAME` to act on specific jobs.

Edge prepares different jobs concurrently, so their hooks can overlap. Keep per-job output separate when your scripts write files.

## Environment variables

| Variable | Value |
| - | - |
| `THREETOONEGO_APP` | `edge` |
| `THREETOONEGO_HOOK_PHASE` | `pre` or `post` |
| `THREETOONEGO_HOOK_SCRIPTS_DIR` | The hook scripts folder |
| `THREETOONEGO_EDGE_ID` | This Edge's ID |
| `THREETOONEGO_EDGE_INSTANCE_ID` | This installation's instance ID |
| `THREETOONEGO_JOB_NAME` | Backup job name |
| `THREETOONEGO_JOB_ROOT` | Job folder inside the container |
| `THREETOONEGO_STATE_KEY` | Key used for the job's local state |
| `THREETOONEGO_LAST_STATUS` | Job's last status, such as `success` |
| `THREETOONEGO_LAST_ERROR_CATEGORY` | Category of the last error, if any |
| `THREETOONEGO_LAST_ERROR_DETAIL` | Detail of the last error, if any |
| `THREETOONEGO_STORED_AS` | Filename of the last upload on Central |
| `THREETOONEGO_PRUNED` | Old snapshots Central removed after the last upload |
| `THREETOONEGO_DUPLICATE` | `true` if Central already had the last upload |
| `THREETOONEGO_PENDING_ARCHIVE` | Staged archive waiting to upload, if any |
| `THREETOONEGO_PENDING_FINGERPRINT` | Fingerprint of the staged archive |
| `THREETOONEGO_PENDING_TIMESTAMP` | Timestamp of the staged archive |
| `THREETOONEGO_UPLOAD_ID` | Current upload session ID |
| `THREETOONEGO_UPLOAD_OFFSET` | Bytes uploaded so far |
| `THREETOONEGO_NEXT_RETRY_AT` | When a failed upload will retry |

In the **pre** command these describe the job's state from its previous run. In the **post** command they describe the run that just finished.

## Example: report each job to a health check

```sh after-job.sh theme={null}
#!/bin/sh
# Ping a health check per job; append /fail when the job needs attention.
url="https://hc-ping.com/your-uuid/$THREETOONEGO_JOB_NAME"
case "$THREETOONEGO_LAST_STATUS" in
  success|skipped_unchanged|skipped_empty) ;;
  *) url="$url/fail" ;;
esac
curl -fsS -m 10 "$url" > /dev/null
```

Common `THREETOONEGO_LAST_STATUS` values after a job:

| Status | Meaning |
| - | - |
| `success` | Uploaded to Central |
| `skipped_unchanged` | Nothing changed since the last backup |
| `skipped_empty` | The folder had no files to back up |
| `retry_scheduled`, `waiting_retry` | Upload failed and will be retried |
| `circuit_open` | Central was unreachable too many times; pausing before retrying |
| `manual_intervention_required` | Retries ran out; check the job in Edge's UI |
| `unexpected_exception` | Something else went wrong; see Edge's logs |

Set **Post Command** to `after-job.sh`.

<Note>
  The Edge image is a minimal Alpine image with `sh` and `curl`. Other tools, such as database clients, aren't included. To dump a database before a backup, run the dump on the host on a schedule ahead of Edge's cycle.
</Note>
