用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
直接命令不会经过审查 Prompt;运行前请先检查来源。
npx skills add https://github.com/laicluse/agent-fieldkit --skill keepalive命令会保持在同一行。复制前请横向滚动并检查完整内容。
想先保存到本地?可下载 SkillsMP 当前能够提供的文件。
Use when corrective work, migrations, living docs, or temporary diagnostic tests leave superseded residue, or before handoff.
Use when corrective work, migrations, living docs, or temporary diagnostic tests leave superseded residue, or before handoff.
Reference for git-discipline commit bodies, trailers, hook denials, examples, and escape hatches.
正在显示 SKILL.md
| name | keepalive |
| description | Probe whether a rover needs a heartbeat in the current host session and set it up when needed. |
| user-invocable | false |
| effort | low |
if [ -n "${CLAUDE_PLUGIN_ROOT:-}" ]; then
node "${CLAUDE_PLUGIN_ROOT}/bin/check-broadcast"
fi
If the command produces output, the autonomous plugin was updated since the last time you saw the broadcast on this machine. Show the output verbatim in a markdown block, prefixed with one short sentence ("autonomous was updated; here is what changed."). Then continue with the rest of this skill.
If the command produces no output, say nothing about updates and proceed.
The helper writes the sentinel only when stdout was non-empty, so a silent
run does not mark the version as seen. In agents that do not set
CLAUDE_PLUGIN_ROOT the broadcast is intentionally skipped; that is the
guard's purpose, not an oversight.
The front door to the autonomy layer. A mission calls this skill once, at startup, and asks a single question:
Am I in a persistent process, or in an interactive session that stops between turns and needs a heartbeat to keep itself alive?
Keepalive answers that question by itself, from the runtime, and acts on the answer. The caller does not have to know anything about cron internals; it does not pass a flag, an env var, or a "skip cron" instruction. It invokes keepalive and uses what comes back.
The caller used to have to know whether its session needed a heartbeat and tell the mission "skip the cron", leaking the autonomy layer's internals into whatever dispatches it. Keepalive moves that decision where it belongs: the autonomy layer probes its own runtime and decides. (The autonomous README carries the full interactive-vs-persistent rationale.)
The signal is tool availability, not an environment flag and not a caller contract.
Determine whether CronCreate is reachable in this process. Inspect the available tool inventory: CronCreate is either a directly available tool or appears in the deferred-tool list loadable via ToolSearch (select:CronCreate). If it is present or loadable, treat CronCreate as available. If it is genuinely absent (not in the tool list and ToolSearch returns nothing for it), treat it as unavailable.
Branch on the result:
CronCreate available, so an interactive session. The harness exposes the heartbeat machinery because this session needs it: it goes idle between turns. Set the heartbeat up. Invoke autonomous:cron via the Skill tool to CronCreate at * * * * * with the loop-file path the caller passed, exactly as the cron setup step describes. Return the job id to the caller so it writes cron_job_id: <id> into the loop file.
CronCreate unavailable, so a persistent process. Nothing exposes a heartbeat because nothing here pauses; the process drives the phase machine to completion in one run and exits. Do not create a cron. Return the sentinel none (persistent process) so the caller writes cron_job_id: none (persistent process) into the loop file and proceeds straight into the first phase. The loop-file discipline is still kept (an interactive session can wake the file later if this run dies), but no heartbeat is scheduled.
Keepalive hands the caller exactly one value:
none (persistent process) (no heartbeat; the caller drives to completion).The caller (see rover setup) writes that value into the loop file's cron_job_id field and continues. In interactive mode the rest of the loop's cron-dependent behaviour (STANDBY backoff, interjection reschedule, wake restore) is live. In persistent mode those steps are moot: the phase machine runs once, end to end, and the mission ends through stop.
This is a deliberate design choice, not a natural law: the autonomy layer treats CronCreate availability as the interactive-vs-persistent signal. The probe is only correct when need and availability coincide: a host that runs a mission as a persistent process must not expose CronCreate, and a host whose sessions go idle must expose it. Capability and need are two facts braided into one on purpose, because the probe needs no coordination between the caller and the host: an explicit flag would require both sides to agree on a name and a value, and that agreement is itself state this design eliminates. The trade is that a host changing its tool configuration is also changing session-mode semantics; that coupling is the price of the zero-coordination contract.
A host that wants persistent/continuous mode withholds the cron tools, for example by adding CronCreate, CronDelete, and CronList to its disallowed-tools list.
Degradation when the assumption is not yet met. If a persistent host still exposes CronCreate, the probe reports interactive and schedules a cron. On the normal path that cron is dead weight: a process that runs to completion never goes idle, so the heartbeat never fires and is torn down with the session. The mission still drives to completion through its phase machine; the cost is one wasted CronCreate call, not a broken run. On an abnormal exit (the process is killed or preempted mid-phase) the scheduled cron can outlive the session the way any orphan cron can (see cron's note on crons surviving a SessionStart:resume); the wake restore path reaps such an orphan on the next manual relight. Either way the fix belongs on the host side (withhold the cron tools so the probe reports persistent), not here; this skill does not invent an env-var fallback to second-guess the tool probe.
Keepalive does not write the loop file: the caller owns that and keepalive only returns the value for cron_job_id. It is a one-shot setup probe, not a phase, and it never touches the loop-file format.