Resume ClawedBack
SkillAI & modelsResume ClawedBack after a restart. Starts the web server, resumes polling, and rebuilds config if missing. Use when starting a new Claude session in an existing ClawedBack install, or when the user says 'resume', 'start', 'restart', 'begin polling', or 'oc-resume'.
Available today. Use it from your connected AI after setup.
No other account needed.
Connect ahel once, and every AI you use reads what you have installed.
Then ask your AI: use the Resume ClawedBack skill
What this skill tells your AI
The instructions your AI receives, as published by mfielding92/clawedback in .claude/skills/oc-resume/SKILL.md and read by ahel’s review.
Restart the server and polling after a Claude Code session restart. Self-healing — if the config file is missing, it detects the setup and rebuilds it.
Step 1: Locate the project
PROJECT_ROOT="$(pwd)"
echo "Project root: $PROJECT_ROOT"
ls "$PROJECT_ROOT/.claude/skills/oc-poll/scripts/main.py" 2>/dev/null && echo "Server found" || echo "ERROR: Not in an ClawedBack project directory"
If .claude/skills/oc-poll/scripts/main.py doesn't exist, tell the user to cd into their ClawedBack directory first. STOP.
Step 2: Check for existing config
cat "$PROJECT_ROOT/data/clawedback.json" 2>/dev/null || echo "NO_CONFIG"
If config exists → skip to Step 5 (use the saved config).
If NO_CONFIG → proceed to Step 3 (auto-detect and rebuild).
Step 3: Auto-detect the setup
Run all of these to determine the environment:
# Who are we?
echo "USER=$(whoami)"
echo "UID=$(id -u)"
# Are we in tmux?
[ -n "$TMUX" ] && echo "TMUX=yes" || echo "TMUX=no"
# Is IS_SANDBOX set?
[ "$IS_SANDBOX" = "1" ] && echo "SANDBOX=yes" || echo "SANDBOX=no"
# Is there a venv?
[ -d "$PROJECT_ROOT/.venv" ] && echo "VENV=yes" || echo "VENV=no"
# What Python are we using?
which python3
# Can we find the venv python?
[ -f "$PROJECT_ROOT/.venv/bin/python" ] && echo "VENV_PYTHON=$PROJECT_ROOT/.venv/bin/python" || echo "VENV_PYTHON=none"
# Is FastAPI importable from system python?
python3 -c "import fastapi" 2>/dev/null && echo "SYSTEM_FASTAPI=yes" || echo "SYSTEM_FASTAPI=no"
# Is FastAPI importable from venv python?
[ -f "$PROJECT_ROOT/.venv/bin/python" ] && "$PROJECT_ROOT/.venv/bin/python" -c "import fastapi" 2>/dev/null && echo "VENV_FASTAPI=yes" || echo "VENV_FASTAPI=no"
# SSL certs?
[ -f "$PROJECT_ROOT/.claude/skills/oc-poll/scripts/fullchain.pem" ] && echo "SSL_LOCAL=yes" || echo "SSL_LOCAL=no"
ls /etc/letsencrypt/live/*/fullchain.pem 2>/dev/null | head -1 || echo "SSL_LETSENCRYPT=none"
# What port?
echo "PORT=${OC_PORT:-8080}"
# Host URL — check env, then detect adapter IP
echo "HOST_URL=${OC_HOST_URL:-}"
hostname -I 2>/dev/null | awk '{print "ADAPTER_IP=" $1}' || ip -4 addr show scope global | grep -oP '(?<=inet\s)\d+(\.\d+){3}' | head -1 | xargs -I{} echo "ADAPTER_IP={}"
# Whisper config?
echo "WHISPER_MODEL=${OC_WHISPER_MODEL:-turbo}"
echo "WHISPER_DEVICE=${OC_WHISPER_DEVICE:-auto}"
# Non-root users on the system
ls /home/ 2>/dev/null
# Is the server already running?
curl -sk http://localhost:${OC_PORT:-8080}/api/health 2>/dev/null || echo "SERVER_DOWN"
# Claude binary location
command -v claude 2>/dev/null || echo "$HOME/.local/bin/claude"
Step 4: Determine mode from detection
Use this logic:
if UID == 0:
if IS_SANDBOX == 1:
MODE = "c" # System install, root, no venv, no permissions
else:
MODE = "b" # Portable root with venv
else:
MODE = "a" # Portable user with venv
For the Python command:
if MODE == "c" (no venv):
PYTHON = "python3"
PIP_FLAGS = "--break-system-packages"
else:
PYTHON = "$PROJECT_ROOT/.venv/bin/python"
# Verify venv python works:
$PYTHON -c "import fastapi" || PYTHON = "python3" # fallback
For SSL, check in order:
- Let's Encrypt certs at
/etc/letsencrypt/live/*/→ use--publicand--privatewith those paths - Local certs at
.claude/skills/oc-poll/scripts/fullchain.pemand.claude/skills/oc-poll/scripts/privkey.pem→ use--ssl - Neither → no SSL (HTTP)
For the non-root username (Mode B/C):
- Check
ls /home/for a single user → use that - If multiple users, check
data/sessions/install_mode.jsonfor a saved username - If still unknown, ask the user
For the claude binary:
CLAUDE_BIN="$(command -v claude 2>/dev/null || echo "$HOME/.local/bin/claude")"
# For root, also check the non-root user's path:
[ "$(id -u)" -eq 0 ] && [ -f "/home/$USERNAME/.local/bin/claude" ] && CLAUDE_BIN="/home/$USERNAME/.local/bin/claude"
Step 5: Start the server
First check if it's already running:
curl -sk http://localhost:${OC_PORT:-8080}/api/health 2>/dev/null
If health check succeeds → server is already running, skip to Step 6.
If not running, build the server command from the config (or detected values):
First kill any leftover server process:
pkill -f "python3 main.py" 2>/dev/null || true
sleep 1
Mode A (user, venv):
cd "$PROJECT_ROOT/.claude/skills/oc-poll/scripts" && source "$PROJECT_ROOT/.venv/bin/activate"
nohup python main.py $SSL_FLAGS > "$PROJECT_ROOT/data/logs/server.log" 2>&1 &
sleep 1 && pgrep -f "python3 main.py" | tail -1 > "$PROJECT_ROOT/data/server.pid"
Mode B (root, venv):
cd "$PROJECT_ROOT/.claude/skills/oc-poll/scripts" && source "$PROJECT_ROOT/.venv/bin/activate"
nohup python main.py $SSL_FLAGS > "$PROJECT_ROOT/data/logs/server.log" 2>&1 &
sleep 1 && pgrep -f "python3 main.py" | tail -1 > "$PROJECT_ROOT/data/server.pid"
Mode C (root, system python):
cd "$PROJECT_ROOT/.claude/skills/oc-poll/scripts"
nohup python3 main.py $SSL_FLAGS > "$PROJECT_ROOT/data/logs/server.log" 2>&1 &
sleep 1 && pgrep -f "python3 main.py" | tail -1 > "$PROJECT_ROOT/data/server.pid"
Where $SSL_FLAGS is:
- No SSL: (empty)
- Local SSL:
--ssl - Let's Encrypt:
--public /etc/letsencrypt/live/$DOMAIN/fullchain.pem --private /etc/letsencrypt/live/$DOMAIN/privkey.pem
Verify it started:
sleep 3
kill -0 $(cat "$PROJECT_ROOT/data/server.pid") 2>/dev/null && echo "Process alive" || echo "PROCESS DIED"
curl -sk http://localhost:${OC_PORT:-8080}/api/health
If it died, show the log:
tail -30 "$PROJECT_ROOT/data/logs/server.log"
Help debug. STOP if server won't start.
Step 6: Start polling
CronCreate with cron "*/1 * * * *" and prompt "/oc-poll"
Verify with CronList.
Step 6.5: Recover interrupted workflows
Check for any in-progress approval chains that were interrupted by the crash:
cat "$PROJECT_ROOT/data/sessions/workflows.json" 2>/dev/null
If any workflow has "status": "in_progress", find the step with "status": "pending". Re-queue that step's approval request:
cd "$PROJECT_ROOT/.claude/skills/oc-poll/scripts" && python queue_manager.py write '{
"content": "**Resumed workflow: WORKFLOW_NAME** (Step N/M)\n\nThis workflow was interrupted and is resuming.\n\nNext action: STEP_DESCRIPTION\n```\nSTEP_COMMAND\n```\n\nApprove? Reply **yes** or **no**.",
"type": "approval_request",
"metadata": {"workflow_id": "ID", "step": N, "total_steps": M}
}'
If no workflows.json exists or no workflows are in progress, skip this step.
Step 7: Run one poll cycle to confirm everything works
cd "$PROJECT_ROOT/.claude/skills/oc-poll/scripts" && $PYTHON queue_manager.py peek
If this returns valid JSON ({"pending": N}), the whole stack is working.
Step 8: Write config (only after everything works)
Only write the config file AFTER Steps 5-7 all succeeded. This way a broken config is never persisted.
Write data/clawedback.json:
cat > "$PROJECT_ROOT/data/clawedback.json" << JSONEOF
{
"mode": "$MODE",
"project_root": "$PROJECT_ROOT",
"username": "$USERNAME",
"host_url": "$HOST_URL",
"python": "$PYTHON",
"claude_bin": "$CLAUDE_BIN",
"port": ${OC_PORT:-8080},
"ssl": {
"enabled": $SSL_ENABLED,
"cert": "$SSL_CERT",
"key": "$SSL_KEY"
},
"whisper": {
"model": "${OC_WHISPER_MODEL:-turbo}",
"device": "${OC_WHISPER_DEVICE:-auto}"
},
"server_cmd": "$SERVER_CMD",
"resume_cmd": "$RESUME_CMD",
"configured_at": "$(date -Iseconds)"
}
JSONEOF
Where:
$HOST_URLis the adapter IP (auto-detected fromhostname -I), or fromOC_HOST_URLenv var, or from the previous config. Falls back to adapter IP if unknown.$SSL_ENABLEDistrueorfalse$SSL_CERT/$SSL_KEYare the cert paths or empty strings$SERVER_CMDis the full command to start the server (for future reference)$RESUME_CMDis the full tmux command to restart ClawedBack:- Mode A:
tmux new -s clawedback 'cd $PROJECT_ROOT && claude' - Mode B:
tmux new -s clawedback 'cd $PROJECT_ROOT && sudo -E $CLAUDE_BIN' - Mode C:
tmux new -s clawedback 'cd $PROJECT_ROOT && sudo -E $CLAUDE_BIN --dangerously-skip-permissions'
- Mode A:
Step 9: Summary
ClawedBack resumed!
Mode: $MODE_NAME
Server: $PROTOCOL://localhost:$PORT (PID: $PID)
Polling: CronCreate every 1 minute
Auth token: (run /oc-token to view)
To reconnect to this tmux session later:
tmux attach -t clawedback
If tmux wasn't detected, warn:
WARNING: You are not in tmux. Polling will stop when this terminal closes.
To fix: exit, then run:
$RESUME_CMD
Using the Config (for other skills)
Any skill can read the config to find paths and settings:
cat "$PROJECT_ROOT/data/clawedback.json"
Or specific fields:
python3 -c "import json; c=json.load(open('$PROJECT_ROOT/data/clawedback.json')); print(c['python'])"
Signals
- GitHub stars
- 23
- Last commit
- Aug 2026
Advanced
- Catalog kind
- skill
- Gateway key
oc-resume- Source
- github.com/mfielding92/clawedback