Skip to content

Instantly share code, notes, and snippets.

@simesy
Created February 15, 2026 00:24
Show Gist options
  • Select an option

  • Save simesy/128bcaf50e8166d1628fab625106f1c8 to your computer and use it in GitHub Desktop.

Select an option

Save simesy/128bcaf50e8166d1628fab625106f1c8 to your computer and use it in GitHub Desktop.
Unfurl mechanic.dev exported task config into folder per task
#!/usr/bin/env bash
# Usage: mechanic_export_unfurl.sh [file] (default: raw_export.json)
# Reads an encode JSON array of Mechanic tasks (using the Export feature) and writes each task as a folder:
# [task name]/config.json - task JSON without script (pretty-printed)
# [task name]/script.liquid - script content with newlines decoded
# Handles escaped/double-encoded JSON (if the file is a JSON string containing the array).
set -euo pipefail
SCRIPT_DIR=$(cd -- "$(dirname "$0")" && pwd)
DEFAULT_INPUT="${SCRIPT_DIR}/raw_export.json"
input="${1:-$DEFAULT_INPUT}"
if [[ "$input" == "-" ]]; then
raw=$(cat)
else
if [[ ! -r "$input" ]]; then
echo "expand.sh: cannot read $input" >&2
exit 1
fi
raw=$(cat "$input")
fi
# If content is an escaped JSON string (e.g. "[{\"name\":...}]"), decode once to get the array
json=$(echo "$raw" | jq -c 'if type == "string" then fromjson else . end')
# Require a non-empty array
len=$(echo "$json" | jq 'length')
if [[ -z "$len" ]] || [[ "$len" -lt 1 ]]; then
echo "expand.sh: no tasks found in input (expected a JSON array)." >&2
exit 1
fi
for i in $(seq 0 $(( len - 1 )) ); do
task=$(echo "$json" | jq -c ".[$i]")
name=$(echo "$json" | jq -r ".[$i] | .name")
if [[ -z "$name" ]]; then
name="task_$i"
fi
dir="$name"
# Avoid overwriting different tasks with same name
base="$name"
n=1
while [[ -d "$dir" ]] && [[ "$(jq -c . "${dir}/config.json" 2>/dev/null)" != "$(echo "$task" | jq -c 'del(.script)')" ]]; do
dir="${base} (${n})"
n=$(( n + 1 ))
done
mkdir -p "$dir"
echo "$task" | jq 'del(.script)' | jq '.' > "${dir}/config.json"
echo "$task" | jq -r '.script // ""' > "${dir}/script.liquid"
echo "$dir"
done
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment