skills/handoff/SKILL.md
--- name: handoff description: Get an agent past a browser/UI wall it can't (or must not) cross on its own — a login-gated dashboard, a CAPTCHA, a 2FA prompt, an API that keeps rejecting the write, or an irreversible click that policy says a human must make. This skill is an ESCALATION LADDER, not a first move: it tells you to try the automated browser surfaces FIRST (Chrome-in-Claude, computer-use, an autonomous browser sub-agent) and only fall back to the Handoff app — a wrapper browser that h
npx skillsauth add razbakov/skills skills/handoffInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Handoff is the backup, never the opening move. Automated browser control is faster, doesn't interrupt the human, and handles the overwhelming majority of UI work. Only escalate to a human handoff when you hit a genuine wall. Walk the ladder top-to-bottom and stop at the first tier that can do the job.
Before any browser at all: is there a gh, gog, netlify, vercel, a dedicated
MCP (Linear, Slack, Gmail, Calendar…), or a REST endpoint? These are faster and
more reliable than any UI. Only when there is no programmatic path — or it fails
(auth, a 422 like the org.wedance.vip DNS case, a missing scope) — move to a browser.
Drive the UI yourself. In rough order of preference:
mcp__claude-in-chrome__*) — the human's real, already-
authenticated Chrome. Best when they're already logged into the site. DOM-aware.mcp__computer-use__*) — native desktop control, for native
apps or when the Chrome surface can't reach it.If one of these completes the task, you are done — do not open Handoff.
Escalate to a guided human handoff when, and only when, one of these is true:
If you'd otherwise type "please go to X, click Y, then Z and tell me when done" — that is the signal. Send a Handoff instead: same instructions, but beside the live page, with a Proceed button that reports back.
DIR="${HANDOFF_DIR:-$HOME/Projects/handoff}" # override with HANDOFF_DIR if you keep it elsewhere
if ! command -v handoff >/dev/null 2>&1; then
[ -d "$DIR" ] || git clone https://github.com/razbakov/handoff "$DIR" || {
echo "Handoff not installed and clone failed. Install it manually, then rerun." >&2
exit 1
}
( cd "$DIR" && npm install && npm link )
fi
command -v handoff >/dev/null 2>&1 || { echo "handoff still not on PATH after install" >&2; exit 1; }
Requires Node + npm. npm link puts the handoff command on PATH. Idempotent —
safe to run every time; it no-ops once installed. It fails loudly rather than
silently if neither a local checkout nor the repo is reachable, so you never think
a handoff was sent when the tool isn't there.
Build the spec inline from flags — you never author JSON:
result=$(handoff do \
--title "<short spoken title>" \
--url "<the page the human should land on>" \
--intro "<one line: why this matters / why it's manual>" \
--note "<the exact values or the one thing that's easy to get wrong>" \
--step "<step 1>" --step "<step 2>" --step "<step 3>" \
--timeout 1800)
code=$? # 0 = done, 2 = blocked, 3 = timeout
handoff do delivers the task, blocks until the human resolves it, then prints the
result JSON — {status, notes, steps, completedAt} — and exits with the code above.
Delivery surface (default: Telegram). The human should do the step in their OWN
browser — real cookies, 1Password/Bitwarden, passkeys, and it works on their phone —
not an isolated embedded one. So by default the handoff arrives as a Telegram
message with an "Open the page ↗" link button and ✓ Done / ⚠ Blocked buttons;
they tap the link, do it where they're already logged in, and tap a button. Replying
to the message adds a note back to the agent (so "Blocked" can say why). Requires
~/.config/telegram/.env (ENVOY_BOT_TOKEN + the human's chat id) and the bot's
ho: handler — see the repo's telegram/ dir. Use --via app to force the
self-contained Electron window instead (embedded browser + checklist queue, but a
session isolated from the real browser, desktop-only).
0 done → verify the effect programmatically if you can (e.g. re-check DNS,
re-hit the API), then continue.2 blocked → read .notes (the human's message back), fix what they flagged,
and either retry an automated tier or send a corrected handoff.3 timeout → the human hasn't gotten to it; ping them (Telegram) or leave it
queued and move on to other work.Multiple handoff open calls stack in the same window (single-instance FIFO
queue, +N waiting badge); the human clears them one by one and the app auto-advances.
Use open + wait to fan out and collect:
handoff open a.json; handoff open b.json # both queue in one window
handoff wait a.json; handoff wait b.json # block on each in turn
handoff list shows what's pending vs. resolved. handoff new … writes a spec file
without opening it.
--url lands them exactly where the work is — the specific dashboard/zone/page,
not the site root.--note carries the one thing that's easy to fumble — the exact record values,
the field that must match, the toggle that's non-obvious.A, Name = org, Value = 76.76.21.21",
not "configure the record". Backtick inline code renders.--intro so the human trusts the ask ("the API kept
returning 422, so this is a 60-second manual step").status: done is the human's claim; confirm the effect
programmatically when a check exists (the DNS resolves, the domain is Valid, the API
now succeeds) before reporting the task complete.--timeout and handle exit code 3 rather than blocking forever.handoff CLI) — github.com/razbakov/handoff.documentation
Summarize one or more YouTube videos from their links. Use this whenever the user pastes a youtube.com or youtu.be URL (or several) and wants to know what it's about — phrasings like "summarize to telegram", "tldr these videos", "what do these say", "summary of this talk", or just dropping links with no instruction at all. Fetches each video's real transcript via yt-dlp (not the page text, which never contains the transcript), cleans the captions, and writes a per-video summary. Default delivery is Telegram; honor any other surface the user names ("to my notes", "just here in chat", "email it"). Trigger even when the user only pastes bare links — bare YouTube links almost always mean "tell me what's in these".
data-ai
Daily Digest — Chief-of-Staff role consolidates the six top-managers into one Telegram message to the Commander, instead of six. Implements the protocol from agent-proactivity.md.
development
Seed a new or empty Instagram account with a 9-post grid (3×3) so the profile looks established the moment a new visitor lands. Designed for festivals, new businesses, product launches, conferences, communities — any time an empty IG profile would hurt conversion from external traffic (QR scans, flyer drops, cross-promo). Generates assets via /image-from-gemini (per content-publishing rules — never HTML), writes captions with hashtag sets, and outputs a posting order + cadence plan. Trigger generously: phrases like '9 posts for instagram', 'fill my IG', 'starter grid', 'launch grid', 'instagram seed', '9-post grid', 'IG account not to look empty', 'first instagram posts', 'feed bootstrap', '3x3 grid', 'instagram launch content'. Even if the user mentions only one piece (just the images, just the captions, just the order), use this skill — the grid only works as an integrated bundle.
testing
Translate one English blog post into multiple target languages via parallel sub-agents, preserving frontmatter conventions, hero image, and brand voice. Use when the user shares a published English post URL or markdown path and says 'translate it', 'add other languages', 'publish in DE/ES/RU/UK', 'translate to 5 languages', or asks for localized versions of a specific post.