Hand the attended djinn lead off to a fresh context: build a kickoff prompt plus the asks in flight, watchers and open questions, store them with `djinn lead relay write`, and print the relay id. The SessionStart hook injects the record into the next session after /clear. Use at the relay line (a hook line naming the Relay procedure in .djinn/lead/session.md) or when the operator says \"hand off\", \"handoff\", \"relay\" or \"pass the baton\" in a djinn repo. Triggers on: /relay, relay line, ...
Installs into .claude/skills of the current project.
Are you the author of Relay?
Add the live security badge to your README. It updates with every re-scan.
[](https://www.skillsdirectory.com/skills/kurofune-relay)
---
# Generated by djinn-gen-adapters from theme=djinn. DO NOT EDIT — regenerate via djinn-gen-adapters.
# djinn-compat: 1
name: relay
description: "Hand the attended djinn lead off to a fresh context: build a kickoff prompt plus the asks in flight, watchers and open questions, store them with `djinn lead relay write`, and print the relay id. The SessionStart hook injects the record into the next session after /clear. Use at the relay line (a hook line naming the Relay procedure in .djinn/lead/session.md) or when the operator says \"hand off\", \"handoff\", \"relay\" or \"pass the baton\" in a djinn repo. Triggers on: /relay, relay line, hand off, handoff, pass the baton."
---
<!-- djinn-compat-check: begin -->
**Before anything else:** run `djinn skills check --here` in the repo you are working in. If it exits non-zero, stop: relay its output to the user verbatim — it names the fix — and run no other step of this skill. On exit 0, continue.
<!-- djinn-compat-check: end -->
# /relay — hand the lead to a fresh context
`/relay` writes the lead relay record: a kickoff prompt the successor reads
first, plus the three lists the harness must never lose. `djinn lead relay
write` stores it at `.djinn/state/lead-relay.json`; after `/clear` the
SessionStart hook claims it and injects the relay header, the prompt verbatim,
then the lists. The Stop hook records it in the seat ledger.
**Stand aside under `DJINN_SESSION=1`:** the relay hooks are silent there, so a
record would never be claimed. Stop and say so.
## 1. Find the session id
- **At the relay line:** the hook line ends `This session's id is <session-id>.`
Use that id.
- **Otherwise** (the operator asked): use `$CLAUDE_CODE_SESSION_ID`.
The id is required. Without one, stop and say so — never invent it.
## 2. Build the kickoff prompt
One self-contained brief a fresh session can act on without asking anything.
It carries intent, never facts: the successor re-reads every fact
(`.djinn/summoner-state.json`, `bd`, `djinn needs-you`), so point at state
instead of copying it. Shape — drop a section with nothing to say:
```
We're continuing the attended lead seat in <repo>.
Goal: <what the operator is driving at this session, in one or two sentences>
Current state: <what is in motion — drains, beads filed, rulings recorded —
named by bead id and file, as a pointer to re-read>
Next steps: <the concrete next move(s), in order>
Watch out for: <settled decisions, gotchas, what was tried and failed>
Where to look:
- `<path or command>` — <what it holds>
```
Be concrete: bead ids, file paths, commands. Never put an unfiled ask or an
unanswered question only in the prompt — it goes in its list below.
## 3. Build the three lists
| Field | Holds |
|---|---|
| `asks_in_flight` | every operator request heard but not yet filed — the one thing a relay must never lose |
| `watchers` | each thing you were waiting on: `purpose`, `source` (the durable file or command to re-read), `last_event` (the last event you saw from it) |
| `open_questions` | questions you asked the operator that are still unanswered |
A running drain or watcher is a `watchers` entry, not a reason to wait. An
empty list is `[]`.
## 4. Write the record
Write the prompt to a temp file and let `jq` quote it; never hand-escape a
multi-line prompt into JSON:
```bash
prompt_file=$(mktemp)
cat >"$prompt_file" <<'PROMPT'
<the kickoff prompt from step 2>
PROMPT
jq -n --arg sid "<session-id>" --rawfile prompt "$prompt_file" \
--argjson asks '["<ask>"]' \
--argjson watchers '[{"purpose":"<purpose>","source":"<source>","last_event":"<last event>"}]' \
--argjson questions '[]' \
'{source_session_id: $sid, prompt: $prompt, asks_in_flight: $asks, watchers: $watchers, open_questions: $questions}' \
| djinn lead relay write
rm -f "$prompt_file"
```
It prints the relay id. A non-zero exit names the field it refused (a blank
`prompt`, a missing `source_session_id`); fix that field and rerun. Never
write `.djinn/state/lead-relay.json` by hand.
## 5. Report
Print the relay id. Then:
- **From the Relay procedure:** carry on with its step 3 (respawn) in
`.djinn/lead/session.md`.
- **Otherwise:** tell the operator `Saved as relay <relay-id>. Type /clear and
the next session picks up from it.`