| name | reef-pulse |
| description | Run the Moonjelly Reef pulse, an orchestrator to scan and dispatch all automated work on autopilot. |
reef-pulse
Input
Nothing, or a specific issue-id to focus the pulse on a single issue.
ONLY_ISSUE_ID="{issue-id or -}"
SKILL_DIR="{base directory for this skill}"
LOCK_FILE=".agents/moonjelly-reef/pulse.lock"
Setup Guard
Read .agents/moonjelly-reef/config.md. If the file doesn't exist, stop and tell the diver: "🪼 reef-pulse requires setup. Run reef-scope first to configure the reef."
TRACKER_TYPE="{from .agents/moonjelly-reef/config.md tracker field}"
TRACKER_BRANCH="{from .agents/moonjelly-reef/config.md tracker-branch field, or empty string if not set}"
If "$TRACKER_TYPE" != "local-tracker-committed", skip the rest of this section.
If "$TRACKER_BRANCH" is empty or missing from config, warn the user — do not continue:
⚠️ tracker-branch is not set in .agents/moonjelly-reef/config.md. Please add it, then try again.
CURRENT_BRANCH="$(git branch --show-current)"
If "$CURRENT_BRANCH" != "$TRACKER_BRANCH", warn the user — do not continue:
⚠️ Current branch is $CURRENT_BRANCH but the tracker branch is $TRACKER_BRANCH. Please run git checkout $TRACKER_BRANCH first, then try again.
./pull.sh --branch "$TRACKER_BRANCH"
Rules
Shell blocks are literal commands — execute them as written.
Tracker note:
- For local-tracker, run
./tracker.sh and ./merge.sh exactly as written.
- For GitHub, replace
./tracker.sh and ./merge.sh with gh
- For other trackers with MCP issue tools, replace
./tracker.sh issue with their MCP equivalent and ./tracker.sh pr and ./merge.sh pr with gh pr
AFK skill: this skill runs without human interaction. You are the orchestrator — scan, dispatch, and exit. You hold no state; labels are the state. When in doubt: check the labels, make your best judgment, move on. Never block waiting for human input.
0. Fetch context
If "$ONLY_ISSUE_ID" = "-", skip this step — the pulse-loop will scan all labels normally.
If $ONLY_ISSUE_ID is a specific ID, fetch that issue. The pulse-loop will process only this issue instead of scanning all labels:
./tracker.sh issue view "$ONLY_ISSUE_ID" --json body,title,labels
1. Session setup
Acquire lock
Check for an existing pulse.lock file.
If the pulse.lock file exists, another pulse may already be running (or a previous session crashed without cleaning up).
- If
pulse.lock exists, read the start timestamp from it, calculate how long the existing pulse has been running, and report this to the diver: "The reef has been pulsing for {elapsed} ~~~ 🪸 🪸 🐠. There may be a lost diver. Pulse again to find them?" In interactive use, ask the diver. In cron/autopilot use, override automatically.
- If
pulse.lock does not exist (or the diver chose to override), create it with a start timestamp (ISO 8601 UTC) and continue.
Print session header
RUN ONCE PER SESSION.
If this is the first iteration of the pulse (not a recursive call), print the session header:
┌─────────────────────────────────────────────────────────────┐
│ 🪼 MOONJELLY REEF · SESSION LOG │
└─────────────────────────────────────────────────────────────┘
Initialize the session bookkeeping variables:
PULSE_NR=1
AGENT_COUNT_SESSION=0
SESSION_START_TS="$(date +%s)"
2. Start pulse loop
After the session is initialized, read and follow pulse-loop.md from top to bottom for the first pulse-loop iteration.
3. Repeat pulse loop or finish
After each return from pulse-loop.md, decide whether to invoke another pulse-loop iteration or move to session completion.
If "$IS_SESSION_COMPLETE" = "false" and "$AGENT_COUNT_PULSE" -gt 0: the pulse dispatched automated work in this pulse-loop iteration. Re-run pulse-loop.md on the main session without asking confirmation. The loop stays on the main session, never as a sub-agent — this keeps the sequence strictly serial (scan, dispatch, wait, scan again) instead of spawning nested agents. Do NOT release the lock between pulse-loop iterations; the lock persists across the entire session. Re-running pulse-loop.md means following that file again from top to bottom using the updated shell variables already present in the same session.
If "$IS_SESSION_COMPLETE" = "true": no automated work was dispatched this iteration. The pulse has nothing left to do. Continue to step 4.
4. Session completion
RUN ONLY IF "$IS_SESSION_COMPLETE" = "true".
Print SESSION COMPLETE
Compute the final session duration from the session start timestamp:
SESSION_DURATION_SECS="$(( $(date +%s) - SESSION_START_TS ))"
SESSION_DURATION="{format SESSION_DURATION_SECS as XmYYs or HhMMmSSs}"
Print the SESSION COMPLETE box with session stats:
┌─────────────────────────────────────────────────────────────┐
│ 🪼 SESSION COMPLETE │
│ │
│ Duration $SESSION_DURATION │
│ Pulses $PULSE_NR │
│ Agents $AGENT_COUNT_SESSION dispatches │
│ To Land #34 #53 │
│ Landed #33 #52 │
│ Blocked #56 #57 │
└─────────────────────────────────────────────────────────────┘
- To Land: issues that reached
to-land during this session
- Landed: issues that reached
landed during this session
- Blocked: issues that are blocked or have no actionable label
Print Lore
RUN ONLY IF "$AGENT_COUNT_SESSION" -gt 0.
prep:
SENTENCE_BALLPARK="$((PULSE_NR * 2))"
Dispatch a sub-agent:
Read and follow $SKILL_DIR/lore-writer.md.
SENTENCE_BALLPARK="$SENTENCE_BALLPARK"
The lore-writer sub-agent returns:
CHAPTER="{lore prose returned by the lore-writer sub-agent}"
Print the chapter:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
$CHAPTER
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Print Next Up
Query for to-land and to-scope issues and say how many there are of those.
./tracker.sh issue list --json number,title,labels --limit 100 --search 'label:to-land OR label:to-scope'
X="{the amount of to-land issues}"
Y="{the amount of to-scope issues}"
Print:
The reef awaits new work. 🐚
You have $X open issues to land and $Y open issues to scope.
Run `reef-land` or `reef-scope` to start. 🤿
Release lock
To release the lock, delete the pulse.lock file.
Exit.