From build-loop
Use when coordinating build-loop with peer coding agents, checking Rally Point presence/inbox state, posting handoffs or feedback, validating the embedded Rally Point boundary, or changing the future agent-rally-point spin-out surface.
How this skill is triggered — by the user, by Claude, or both
Slash command
/build-loop:agent-rally-pointThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
<!-- SPDX-FileCopyrightText: 2025-2026 Tyrone Ross, Jr <[email protected]> | SPDX-License-Identifier: Apache-2.0 -->
Build-loop ships a native embedded agent-rally-point capability while the
standalone repo matures. Treat it as a mini-plugin inside build-loop: keep the
substrate logic, docs, tests, and thin build-loop adapters grouped so spin-out
is mechanical later.
| Purpose | Path |
|---|---|
| Substrate package | ${CLAUDE_PLUGIN_ROOT}/scripts/rally_point/ |
| Host-neutral CLI | ${CLAUDE_PLUGIN_ROOT}/scripts/agent_rally.py |
| Slash command | ${CLAUDE_PLUGIN_ROOT}/commands/rally-point.md |
| Hook adapters | ${CLAUDE_PLUGIN_ROOT}/hooks/session-start-rally-point.sh, ${CLAUDE_PLUGIN_ROOT}/hooks/pre-edit-rally-point.sh |
| Build-loop adapters | ${CLAUDE_PLUGIN_ROOT}/scripts/coordination_status.py, ${CLAUDE_PLUGIN_ROOT}/scripts/coordination_rally.py, ${CLAUDE_PLUGIN_ROOT}/scripts/coordination_bootstrap.py |
| Boundary manifest | ${CLAUDE_PLUGIN_ROOT}/scripts/rally_point/plugin_boundary.json |
At the Phase 1 preamble, before the first Rally Point write, the orchestrator must generate or resume the durable run identity:
from scripts.rally_point.build_loop_id import generate_or_resume
execution = generate_or_resume(
workdir=Path.cwd(),
tool="<tool-id>",
session_id="<session-id>",
)
session_id is the ephemeral host session. run_id is caller-chosen legacy
provenance. build_loop_id is the durable human-visible run identity and is
surfaced on Rally Point records as top-level build_loop_id and
build_loop_run_label.
scripts/rally_point/discovery_bridge.py or
scripts/agent_rally.py where; do not hardcode legacy channel roots.scripts/rally_point/post.py::post();
do not append directly to changes.jsonl.build_loop_id separate from producer_metadata.plugin_boundary.json.claude_code, codex, cursor, gemini, or another
lowercase id agreed by the adapter.python3 ${CLAUDE_PLUGIN_ROOT}/scripts/agent_rally.py status --workdir "$PWD" --session-id "$SESSION_ID" --json
python3 ${CLAUDE_PLUGIN_ROOT}/scripts/agent_rally.py heartbeat --workdir "$PWD" --session-id "$SESSION_ID" --task-ref "$TASK_REF" --progress "still working" --json
python3 ${CLAUDE_PLUGIN_ROOT}/scripts/agent_rally.py ack-inbox --workdir "$PWD" --session-id "$SESSION_ID" --tool "$TOOL_ID" --json
python3 ${CLAUDE_PLUGIN_ROOT}/scripts/agent_rally.py boundary --repo "${CLAUDE_PLUGIN_ROOT}" --check --json
python3 ${CLAUDE_PLUGIN_ROOT}/scripts/rally_point/boundary.py --repo "${CLAUDE_PLUGIN_ROOT}" --check --json
Use /agent-rally-point status for the same sensor from Claude Code.
Status/watch envelopes include inbox_latest_messages, a compact doorbell
preview for the newest unread direct/broadcast inbox records. Counts are
session-ack aware; read inbox/<tool>.jsonl or inbox/all.jsonl before acting
on a full message, then run ack-inbox after handling it. Ack cursors live
under inbox/.acks/ and never rewrite the append-only inbox payloads.
Presence is process liveness: it tells peers this session can still write to the channel. Task heartbeat is work liveness: it tells peers whether the session is still on the claimed task, what changed since the last check-in, what evidence exists, and when the next check-in is due.
For long-running tasks, write a heartbeat at task start and then at least every 10 minutes:
python3 ${CLAUDE_PLUGIN_ROOT}/scripts/agent_rally.py heartbeat \
--workdir "$PWD" \
--session-id "$SESSION_ID" \
--tool "$TOOL_ID" \
--model "$MODEL" \
--run-id "$RUN_ID" \
--task-ref "$TASK_REF" \
--status running \
--progress "short update since last check-in" \
--evidence "files/tests/commit-or-handoff-ids" \
--json
Then pass the same --task-ref to status or watch. Health can be
current, stale_check_in, wrong_task, missing, drift_risk, blocked,
or needs_attention. blocked and needs_attention make status report
blocked; stale, missing, wrong-task, and drift-risk states report warn.
roster answers the cross-channel "who's live right now" question in one
command. It walks every <apps_root>/*/sessions/*.json (all repos at
once), keeps sessions whose last_seen is within the stale window, and
builds a parent/child tree from each record's parent link plus the
self-reported spawned fan-out.
python3 ${CLAUDE_PLUGIN_ROOT}/scripts/agent_rally.py roster # live tree, all channels
python3 ${CLAUDE_PLUGIN_ROOT}/scripts/agent_rally.py roster --app ptyd # one channel
python3 ${CLAUDE_PLUGIN_ROOT}/scripts/agent_rally.py roster --json # structured (array of agent objects w/ children + spawned)
python3 ${CLAUDE_PLUGIN_ROOT}/scripts/agent_rally.py roster --stale-secs 300 --all # widen window, keep stale
python3 ${CLAUDE_PLUGIN_ROOT}/scripts/agent_rally.py roster --watch 5 # re-render every 5s
Each row: session_id · app · host:cwd · tool/model · task · last-seen(age) · subagents (Σtotal by-type + live nested count). Children that posted their
own presence nest under the parent; subagents that did not post presence are
reflected by the parent's spawned totals.
So the roster is useful, agents must enrich their presence calls. These
fields are additive and backward-compatible (existing callers keep working):
python3 ${CLAUDE_PLUGIN_ROOT}/scripts/agent_rally.py presence \
--session-id "$SESSION_ID" --tool claude_code --model opus \
--cwd "$PWD" \
--task "what this agent is actually doing right now" \
--parent "$SPAWNING_SESSION_ID" \
--spawned "coder:2,workflow:21,independent-auditor:1"
--cwd / --pid / --host — where it runs (default cwd / this pid / this host).--task — fuller free text (falls back to --phase for display).--parent <session_id> — links a subagent to its spawning agent; omit for top-level.--spawned <type:count,…> — the fan-out an agent self-reports.presence call rewrites last_seen; re-post periodically so the
agent stays in the live window (default 120s). Presence is not task
heartbeat; use agent_rally.py heartbeat for long-running task check-ins.Top-level orchestrators should post --spawned reflecting their dispatched
subagents; each dispatched subagent that can post should set --parent to the
orchestrator's session_id.
uv run pytest scripts/test_build_loop_id.py scripts/rally_point/test_boundary.py scripts/rally_point/test_orchestrator_contract.py scripts/test_agent_rally_roster.py scripts/test_agent_rally_status.py
python3 scripts/agent_rally.py boundary --repo "$PWD" --check --json
When extracting to the standalone plugin, copy the namespaced substrate,
skill, command, hooks, tests, and docs named in plugin_boundary.json.
Build-loop should then keep only the thin adapters that call the standalone
package.
npx claudepluginhub tyroneross/build-loop --plugin build-loopProvides behavioral guidelines to reduce common LLM coding mistakes, focusing on simplicity, surgical changes, assumption surfacing, and verifiable success criteria.
Searches, retrieves, and installs Agent Skills from prompts.chat registry using MCP tools like search_skills and get_skill. Activates for finding skills, browsing catalogs, or extending Claude.