Git-based tool relay system for extending Claude's capabilities. Use this skill at the START of every conversation with Rubait to load system context, run cleanup, and enable tool calls via the GitHub relay repo (ftpuser250/claude). Trigger whenever Rubait says "continue where we left off", "use your tools", "check system status", or starts any technical session. Also trigger when creating new tools mid-conversation using tool_factory.
Install
npx skillscat add ftpuser250/claude Install via the SkillsCat registry.
Rubait Relay System
A git-based tool relay that lets Claude call external tools by pushing requests
to GitHub (whitelisted domain) and reading responses written by a GCP executor.
Session Start Protocol (run every new conversation)
Step 1 — Clone relay repo
git clone https://{PAT}@github.com/ftpuser250/claude /tmp/relay
cd /tmp/relayPAT is provided by Rubait at session start. Ask for it if not given.
Step 2 — Read context.json
Load and report:
- system status (gcp_executor, cf_worker, tools deployed)
- pending_tasks
- tools_available
- last session summary
- any anomalies
Step 3 — Self-cleaning housekeeping
# Run cleanup script
python3 tools/cleanup.py
# If cleanup.py not yet deployed, run manually:Cleanup rules:
requests/→ delete if matching response exists OR timestamp > 24h oldresponses/→ delete if older than 7 dayspending_approval/→ delete if older than 5 minuteslogs/→ delete if older than 30 days- Never delete:
tools/,tools.json,context.json,SKILL.md
If anything deleted:
git add -A
git commit -m "cleanup: session start housekeeping $(date -u +%Y-%m-%dT%H:%M:%SZ)"
git pushStep 4 — Check for stuck requests
Scan requests/ for files with no matching responses/ entry.
Report to Rubait if any found.
Step 5 — Report status
Brief Rubait: tools available, last session date, pending tasks, anomalies.
Step 6 — Ask for HMAC secret
"Paste HMAC secret to enable tool calls, or skip for planning session."
Store in memory as RELAY_SECRET for this session only.
Making a Tool Call
Request format
import hmac, hashlib, json, uuid
from datetime import datetime, timezone
def make_request(tool, args, secret):
req_id = "req_" + uuid.uuid4().hex[:5]
payload = {
"id": req_id,
"tool": tool,
"args": args,
"timestamp": datetime.now(timezone.utc).isoformat(),
"ttl_seconds": 30
}
sig = hmac.new(
secret.encode(),
json.dumps(payload, sort_keys=True).encode(),
hashlib.sha256
).hexdigest()
payload["auth"] = sig
return req_id, payloadPush request
echo '{...}' > /tmp/relay/requests/req_{id}.json
cd /tmp/relay
git add requests/req_{id}.json
git commit -m "request: {tool} {id}"
git pushPoll for response (max 60s)
import time, os, json
def poll_response(req_id, timeout=60):
path = f"/tmp/relay/responses/res_{req_id}.json"
start = time.time()
while time.time() - start < timeout:
os.system("cd /tmp/relay && git pull -q")
if os.path.exists(path):
return json.load(open(path))
time.sleep(3)
return {"status": "timeout", "id": req_id}Handle response
status: ok→ usedatafieldstatus: error→ checkerror.message, retry ifrecoverable: truestatus: pending_approval→ tell Rubait to check phonestatus: timeout→ server may be down, report to Rubaitstatus: rejected→ HMAC mismatch, check secret
Security Levels
| Level | Approval | Examples |
|---|---|---|
read |
None | web_fetch, search, obsidian_search |
write |
None, logged | obsidian_write, task_add, git_commit |
execute |
Phone (Telegram/Discord) | shell_exec, service_restart |
destructive |
Phone with warning | file_delete, db_wipe |
Creating a New Tool (tool_factory)
When Rubait needs a new tool mid-conversation:
- Design the tool (name, description, input/output schema, Python implementation)
- Call tool_factory with full spec including
implementation(Python code as string) - GCP validates syntax, runs tests, registers in tools.json, pushes to GitHub
- Update context.json
tools_availablelist - Tool is live immediately
tool_factory security_level = write — no approval needed unless tool itself is destructive.
Session End Protocol
Step 1 — Update context.json
# Append to session_history
{
"date": "YYYY-MM-DD",
"summary": "one paragraph of what was done",
"tools_used": ["list of tools called"],
"decisions_made": ["list of architectural decisions"]
}
# Update pending_tasks (mark done, add new)
# Update tools_available if new tools created
# Update system status if anything deployedStep 2 — Commit and push
cd /tmp/relay
git add context.json
git commit -m "context: session $(date +%Y-%m-%d) summary"
git pushStep 3 — Confirm to Rubait
"Context saved. Next session resumes from here."
File Structure Reference
ftpuser250/claude/
├── SKILL.md ← this file
├── README.md ← human-readable docs
├── context.json ← cross-session memory (always read first)
├── tools.json ← tool registry
├── requests/ ← Claude writes here
│ └── req_{id}.json
├── responses/ ← GCP writes here
│ └── res_{id}.json
├── pending_approval/ ← awaiting phone confirmation
│ └── req_{id}.json
├── logs/ ← daily activity (30 day retention)
│ └── YYYY-MM-DD.json
└── tools/ ← tool scripts (managed by tool_factory)
├── cleanup.py
├── web_fetch.py
├── task_add.py
├── shell_exec.py
└── tool_factory.pyKnown Limitations
- Round trip latency: ~3-6s (GitHub push + GCP execute + pull)
- TCP-only, whitelisted domains only in bash_tool
- No persistent state between sessions (PAT and HMAC secret re-entered each time)
- GCP executor must be running (check context.json system.gcp_executor status)
- Concurrent requests supported via separate files but responses may arrive out of order
Rubait's Tool Wishlist (not yet built)
- web_fetch, web_search, web_crawler
- obsidian_search, obsidian_write
- task_add (task-inbox.md)
- git_status, git_commit
- shell_exec (sandboxed)
- security_scan (nmap/headers/SSL)
- dotfile_read, dotfile_write
- image_generator (via API)
- youtube_search, youtube_extract
- multi_llm_relay
- tool_factory (meta-tool)
- cleanup (maintenance)