Overnight Factory
v1.0.0Set up an AI agent as an Overnight Software Factory operator. Use when configuring an OpenClaw agent to autonomously handle support tickets end-to-end: recei...
Like a lobster shell, security has layers — review code before you run it.
License
SKILL.md
Overnight Factory
Configure this agent as an autonomous ticket-to-PR operator. Human reviews PRs; agent handles everything else.
Architecture
TinyDesk/support system
→ GitHub issue (assigned to bot account)
→ Email notification to agent inbox
↓
Cron job (every 15min, isolated session)
├─ Email check: detect assignment emails
├─ GitHub poll: catch missed emails (safety net)
└─ Dispatch: spawn subagent per ticket
↓
Subagent (Claude Code)
├─ Analyze issue + screenshots
├─ Explore codebase
├─ Post analysis comment on issue
├─ Implement fix (branch → commit → push)
└─ Open PR → notify human
Setup Steps
1. Identity & Credentials
Create workspace files: IDENTITY.md, USER.md (who you're helping), SOUL.md.
Add .env to workspace:
GITHUB_TOKEN=ghp_...
EMAIL_USER=support@yourdomain.com
EMAIL_PASSWORD=...
Configure git:
git config --global user.name "Your Bot Name"
git config --global user.email "bot@yourdomain.com"
echo "https://bot-username:${GITHUB_TOKEN}@github.com" > ~/.git-credentials
git config --global credential.helper store
2. Verify Claude Code
/path/to/claude --version
/path/to/claude -p --dangerously-skip-permissions --output-format text "echo hello"
Note the exact path — you'll need it.
3. Create the Cron Job
openclaw cron add \
--name "email-check" \
--every 15m \
--session isolated \
--announce \
--to <YOUR-TELEGRAM-CHAT-ID> \ # explicit ID, NOT --channel last
--timeout-seconds 120 \
--description "Check email + GitHub for ticket assignments" \
--message "$(cat /path/to/cron-prompt.txt)"
See references/cron-prompt.md for the full prompt template.
4. Keep HEARTBEAT.md Lightweight
The cron handles email. Heartbeat should only contain tasks that need main-session context (e.g., PR monitoring).
Critical Rules
Cron delivery: Always use --to <explicit-chat-id>. Never --channel last — it doesn't resolve in isolated sessions.
Cron timeout: Keep the prompt fast. Check email → spawn subagents → log → exit. Never wait for subagents inline. 120s is enough.
Error backoff: After 5+ consecutive errors the cron backs off exponentially. Delete and recreate to reset: openclaw cron delete <id> && openclaw cron add ...
Fire-and-forget: Subagents don't reliably call back to Telegram. Have the cron itself announce dispatches in its own reply (the cron reply is what gets delivered).
Validation Checklist
Before going live:
- Send test email to support address — cron picks it up within 15 min
- Cron dispatch reply arrives on Telegram
- Subagent opens a real branch + PR
- Assign a GitHub issue to bot manually — GitHub poll catches it
-
lastDelivered: falseon empty runs is expected (HEARTBEAT_OK is silent by design)
Debugging
# Check cron status
openclaw cron list --json | jq '.jobs[0].state'
# Key fields to check:
# lastRunStatus: "ok" or "error"
# consecutiveErrors: should be 0
# lastDelivered: false on empty runs is normal; false on ticket-dispatch runs is a bug
# lastDeliveryStatus: "not-delivered" = delivery config wrong
# Check recent logs
tail -20 memory/heartbeat-log.jsonl
# Check inbox directly
python3 -c "
import imaplib, ssl
ctx = ssl.create_default_context()
M = imaplib.IMAP4_SSL('imap.ionos.com', 993, ssl_context=ctx)
M.login('user@domain.com', 'password')
M.select('INBOX')
print('Unread:', len(M.search(None, 'UNSEEN')[1][0].split()))
M.logout()
"
Reference Files
references/cron-prompt.md— full cron job prompt template with email check + GitHub pollreferences/ticket-pipeline.md— how to instruct subagents to handle tickets end-to-endreferences/lessons-learned.md— real failure modes and fixes from production use
Files
4 totalComments
Loading comments…
