GitClaw
Back up the OpenClaw agent workspace to a GitHub repo and keep it synced via a cron-driven commit/push script.
Back up the OpenClaw agent workspace to a GitHub repo and keep it synced via a cron-driven commit/push script.
Real data. Real impact.
Emerging
Developers
Per week
Open source
Skills give you superpowers. Install in 30 seconds.
Use this skill automatically when it's installed or reference, and also when the user asks to:
Ask the user for:
openclaw-backup)public or privateDo NOT ask for a Personal Access Token. We use
gh auth.
Check:
git --versionIf missing, install using the best available method:
brew exists:
brew install gitapt-get exists:
sudo apt-get update && sudo apt-get install -y gitdnf exists:
sudo dnf install -y gityum exists:
sudo yum install -y gitpacman exists:
sudo pacman -S --noconfirm gitzypper exists:
sudo zypper install -y gitapk exists:
sudo apk add gitxcode-select exists:
xcode-select --install (this may prompt the user)Re-check:
git --versionOnly notify the user if install failed.
Check:
command -v crontabIf missing, attempt install:
apt-get exists:
sudo apt-get update && sudo apt-get install -y cronsudo systemctl enable --now cron || sudo service cron start || truednf exists:
sudo dnf install -y croniesudo systemctl enable --now crond || trueyum exists:
sudo yum install -y croniesudo systemctl enable --now crond || truepacman exists:
sudo pacman -S --noconfirm croniesudo systemctl enable --now cronie || trueapk exists:
sudo apk add dcronsudo rc-update add dcron default || truesudo rc-service dcron start || trueRe-check:
command -v crontabgh) is installed (auto-install)Check:
gh --versionIf missing, install:
If
brew exists:
brew install ghElse if
apt-get exists (official GitHub CLI packages; preferred):
(type -p wget >/dev/null || (sudo apt-get update && sudo apt-get install -y wget))sudo mkdir -p -m 755 /etc/apt/keyringsout=$(mktemp) && wget -nv -O"$out" https://cli.github.com/packages/githubcli-archive-keyring.gpgcat "$out" | sudo tee /etc/apt/keyrings/githubcli-archive-keyring.gpg > /dev/nullsudo chmod go+r /etc/apt/keyrings/githubcli-archive-keyring.gpgsudo mkdir -p -m 755 /etc/apt/sources.list.decho "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages stable main" | sudo tee /etc/apt/sources.list.d/github-cli.list > /dev/nullsudo apt-get update && sudo apt-get install -y ghElse if
dnf exists:
sudo dnf install -y 'dnf-command(config-manager)' || sudo dnf install -y dnf5-plugins || truesudo dnf config-manager --add-repo https://cli.github.com/packages/rpm/gh-cli.repo || sudo dnf config-manager addrepo --from-repofile=https://cli.github.com/packages/rpm/gh-cli.repo || truesudo dnf install -y gh --repo gh-cli || sudo dnf install -y gh || trueElse if
yum exists:
type -p yum-config-manager >/dev/null || sudo yum install -y yum-utilssudo yum-config-manager --add-repo https://cli.github.com/packages/rpm/gh-cli.reposudo yum install -y ghElse if
zypper exists:
sudo zypper addrepo https://cli.github.com/packages/rpm/gh-cli.repo || truesudo zypper refsudo zypper install -y ghElse if
pacman exists:
sudo pacman -S --noconfirm github-cliElse if
apk exists:
sudo apk add github-cliElse:
gh on this OS.Re-check:
gh --versionOnly notify the user if install failed.
gh (agent runs the flow)Check:
gh auth status --hostname github.comIf NOT authenticated:
Run:
gh auth login --hostname github.com --git-protocol httpsThe terminal flow will show a one-time code and ask the user to authorize.
After login:
gh auth setup-gitVerify again:
gh auth status --hostname github.comIf auth fails, stop and report the exact terminal output.
Workspace dir (where you store SOUL.md, AGENTS.md, etc.):
WORKSPACE_DIR="$HOME/.openclaw/workspace"Ensure the workspace exists:
mkdir -p "$WORKSPACE_DIR"cd "$WORKSPACE_DIR"Initialize repo if needed:
.git does not exist: git initgit branch -M mainConfigure a deterministic commit identity (local-only):
git config user.name "gitclaw.ai"git config user.email "gitclaw-bot@users.noreply.github.com"Determine the authenticated GitHub username (owner):
OWNER="$(gh api user --jq .login)"Repo name and visibility:
REPO="<repo name from user>"public => --publicprivate => --privateEnsure there is at least one commit (required for first push/cron):
test -f .gitclaw.keep || printf "gitclaw initialized: %s\n" "$(date -u '+%Y-%m-%dT%H:%M:%SZ')" > .gitclaw.keepgit add -Agit commit -m "gitclaw: initial backup" || trueCreate or reuse the target repo:
gh repo view "$OWNER/$REPO" >/dev/null 2>&1REMOTE_URL="https://github.com/$OWNER/$REPO.git"git remote set-url origin "$REMOTE_URL"git remote add origin "$REMOTE_URL"git fetch origin main || truegit merge --ff-only origin/main || truegh repo create "$REPO" --public --confirmgh repo create "$REPO" --private --confirmREMOTE_URL="https://github.com/$OWNER/$REPO.git"git remote add origin "$REMOTE_URL" || git remote set-url origin "$REMOTE_URL"Initial push:
git push -u origin mainIf push fails due to conflicts or non-fast-forward:
Create a folder outside the workspace:
mkdir -p "$HOME/.openclaw/gitclaw"Create this script EXACTLY:
Path:
$HOME/.openclaw/gitclaw/auto_backup.shContents:
#!/usr/bin/env bash set -euo pipefailGitClaw deterministic backup (no AI)
export PATH="/usr/local/bin:/opt/homebrew/bin:/usr/bin:/bin:$PATH"
WORKSPACE_DIR="${HOME}/.openclaw/workspace" STATE_DIR="${HOME}/.openclaw/gitclaw" LOG_FILE="${STATE_DIR}/backup.log" LOCK_DIR="${STATE_DIR}/lock"
mkdir -p "${STATE_DIR}"
timestamp() { date -u '+%Y-%m-%dT%H:%M:%SZ'; }
Simple lock to prevent overlapping runs
if ! mkdir "${LOCK_DIR}" 2>/dev/null; then echo "$(timestamp) Skip: already running." >> "${LOG_FILE}" exit 0 fi trap 'rmdir "${LOCK_DIR}" >/dev/null 2>&1 || true' EXIT
if ! command -v git >/dev/null 2>&1; then echo "$(timestamp) ERROR: git not found on PATH. Install git first." >> "${LOG_FILE}" exit 2 fi
if [ ! -d "${WORKSPACE_DIR}/.git" ]; then echo "$(timestamp) ERROR: ${WORKSPACE_DIR} is not a git repo. Run GitClaw setup first." >> "${LOG_FILE}" exit 3 fi
cd "${WORKSPACE_DIR}"
Stage everything
git add -A
If nothing staged, exit quietly
if git diff --cached --quiet; then echo "$(timestamp) No changes." >> "${LOG_FILE}" exit 0 fi
Commit + push
git commit -m "gitclaw backup: $(timestamp)" >> "${LOG_FILE}" 2>&1 git push origin main >> "${LOG_FILE}" 2>&1
echo "$(timestamp) Backup OK." >> "${LOG_FILE}"
Write the script to:
$HOME/.openclaw/gitclaw/auto_backup.shThen:
chmod +x "$HOME/.openclaw/gitclaw/auto_backup.sh"Default schedule: hourly (
0 * * * *). If user provided a different frequency, convert it to a cron expression.
CRON_CMD="$HOME/.openclaw/gitclaw/auto_backup.sh"CRON_LINE="0 * * * * $CRON_CMD"crontab -l 2>/dev/null | grep -F "$CRON_CMD" >/dev/null(crontab -l 2>/dev/null; echo "$CRON_LINE") | crontab -crontab -l | grep -F "$CRON_CMD"$HOME/.openclaw/gitclaw/auto_backup.shtail -n 50 "$HOME/.openclaw/gitclaw/backup.log" || truehttps://github.com/$OWNER/$REPO~/.openclaw/gitclaw/auto_backup.shNo automatic installation available. Please visit the source repository for installation instructions.
View Installation Instructions1,500+ AI skills, agents & workflows. Install in 30 seconds. Part of the Torly.ai family.
© 2026 Torly.ai. All rights reserved.