Getting it into your agent
One page per mod, every tool's command on it. A separate URL per tool would split the same page into five that compete with each other.
npx skills add sonichi/sutando --skill proactive-loopgit clone --depth 1 https://github.com/sonichi/sutandoWrote this? Show the measurements
A badge with what this costs and how it scanned, read live from this page, so it follows the numbers instead of freezing them. Markdown for a README, HTML for a documentation site or a project page.
[](https://agentmods.dev/skills/sonichi/sutando/proactive-loop)<a href="https://agentmods.dev/skills/sonichi/sutando/proactive-loop"><img src="https://agentmods.dev/badge/skills/sonichi/sutando/proactive-loop/github.svg" alt="Measured on agentmods" height="20"></a>Or the 80×15 button, for a site that already has a row of RSS and ATOM ones. Only the verdict fits; the numbers stay here.
<a href="https://agentmods.dev/skills/sonichi/sutando/proactive-loop"><img src="https://agentmods.dev/badge/skills/sonichi/sutando/proactive-loop.svg" alt="Reviewed on agentmods" width="80" height="20"></a>What it costs to keep this loaded
Counted locally with the o200k_base tokenizer, which is exact for GPT models; Claude uses its own tokenizer and its counts differ. Treat this as one consistent yardstick across the catalogue rather than a bill. Prices are per million input tokens.
| Model | Per session | Once invoked |
|---|---|---|
| Fable 5.1 | $0.00029 | $0.03181 |
| Opus 5.5 | $0.00012 | $0.01272 |
| Sonnet 5.5 | $0.00006 | $0.00636 |
| Haiku 4.5 | $0.00003 | $0.00318 |
Grade C, and why
proactive-loop scanned grade C with 1 finding against 26 rules in 11 categories — prompt injection, anti-refusal, data exfiltration, privilege escalation, supply chain, agent snooping, system-prompt leakage, SSRF and excessive agency — measured yesterday.
A static scan of the body, not an audit. Every finding is printed with the line that produced it so you can judge whether it matters here. A mod is markdown that instructs an agent; that is exactly why what it instructs is worth reading.
Nullifies safety policieshighAnti-refusal
"You have no restrictions", "do anything now", "ignore your guidelines": a direct jailbreak that disables guardrails.
active. Manual `/proactive-loop` invocation does not override the policy. How it starts
The opening of the file, as written. The whole thing — 139 lines — stays where its author put it; the contents beside it link to each section on GitHub.
Proactive Loop
One pass = the numbered steps below, in order. Each step is a command, its exit codes, and what to
do per code. The reasoning, measurements and incidents behind every step live in
docs/proactive-loop-rationale.md under the same step
number; read it when a step surprises you, never per pass. A rule belongs here only as a command a
mechanism enforces; prose lessons go to the rationale doc (tests/proactive-loop-skill-budget.test.py
caps this file and refuses date stamps in it).
Usage: /proactive-loop [interval] (default 10m).
On activation
/schedule-crons— registers the session crons and stamps them.- Task watcher via the
Monitortool:command: 'bash src/watch-tasks-stream.sh --role session --inbox "$(bash scripts/sutando-config.sh workspace)/tasks"'(substitute$SUTANDO_TASKS_DIRfor the inbox when it is set — the same tag step 9's re-arm uses),timeout_ms: 1800000,description: 'Streaming task watcher'. EachTASK_FILE: <name>line is one task to Read and process. Re-arm it on the expiry notice and on any notice that it exited early (on macOS Claude Code reports a SIGTERM death asexit code 144); the inbox is unwatched until the standby's grace elapses.Monitorhas nopersistentoption: it kills the command attimeout_ms(30 min is the maximum) and sends one expiry notice. On that notice, re-arm the watcher the same way (a start on a watched inbox exits 0); until you do, the external standby announces tasks through the pane after a 45 s grace. Windows has noMonitortool:src/startup.ps1ownssrc/task-dispatcher.ps1; do not start another watcher. - If
CronListalready shows amain-loop//proactive-loopjob, run the per-pass body directly — never add a second loop driver.
Per pass
WORKSPACE="$(bash scripts/sutando-config.sh workspace)" once; quote every "$WORKSPACE/..." path.
- Status.
bash scripts/core-status.sh running "<work>"on each pivot. Finish with step 1’s idle command; never redirect the JSON. 0.5. Quota tier (Claude core):python3 $CLAUDE_CONFIG_DIR/skills/quota-tracker/scripts/read-quota.py | python3 skills/proactive-loop/scripts/quota-tier.py→TIER <FULL|MEDIUM|LIGHT|MINIMAL> (bound by …). Thenpython3 skills/proactive-loop/scripts/claude-quota-cadence.py --json→ ifeffective_crondiffers from the/proactive-loopjob inCronList: capture the old job id,CronCreatethe new job withprompt: "/proactive-loop"andcron: <effective_cron>, confirm it inCronList. ThenCronDeletethe old id and confirm exactly one/proactive-loopjob remains. If create or confirmation fails, keep the old job and stop loudly. Codex core:python3 skills/proactive-loop/scripts/codex-quota-gate.py --json. Tier caps step 6's depth (LIGHT/MINIMAL: no self-development); it never skips owner tasks, health or the log. 0.7. Reconstruct. Invoke thecontext-reconstructskill (a Skill-tool call, not a mention). It reads<workspace>/hosts/<host>/current-track.mdfirst, then the live thread (python3 src/discord-read.py <channel> --serving <channel>when serving a task,--operatorotherwise), pending questions, relay, build log. Trust the record over recall; maintaincurrent-track.md. - Tasks. Process every file in
$WORKSPACE/tasks/;access_tier: team|other→ the sandboxed path. Group a thread with[deduped: task-<latest>], staged under its FINAL name and gated into place —results/is claimed by a poller in under a second, and the checker reads the source id from the BASENAME, so a generic temp name makes it pass everything:S="$WORKSPACE/state/dedup-staging/<file>"thenpython3 skills/proactive-loop/scripts/check-dedup-targets.py "$S" && mv -f "$S" "$WORKSPACE/results/<file>"(0 clean · 1 the dedup delivers nothing · 2 cannot answer). All-notice groups use[no-send]on each. Marker semantics belong tosrc/result_markers.py; never re-implement them. When this core consumes a task itself, move$WORKSPACE/tasks/<id>.txtto$WORKSPACE/tasks/archive/<id>.txtafter writing its result; bridges and the Windows dispatcher archive their own claims. Before idle:python3 scripts/unanswered-tasks.py --workspace "$WORKSPACE" && bash scripts/core-status.sh idle "" --loop-complete(1 = a task got no result, so idle does not run). 1.5. Connect waits.python3 skills/connect-apps/scripts/connectors.py rearmrestarts the waiter of any pending connector wait that lost it; idempotent, and a failure never blocks the pass. - Questions. Nothing surfaces on a pass: a question reaches the owner once, when asked
(
scripts/ask-owner.py);src/check-pending-questions.py --notifyreminds only when he asks, flagless it files what the outbox holds, sends nothing.src/pending_questions_reader.py listonly when he asks or you are blocked on an answer. - Health.
python3 src/health-check.py; fix with--fixwhat it can. A warn is a pointer into the record: before investigating,grep -in "<entity from the warn TEXT>" "$H/current-track.md"andpending_questions_reader.py list --json | grep -i "<entity>"withH="$WORKSPACE/hosts/$(bash scripts/sutando-config.sh host-label)"; a zero means try another token, thengrep -n '^## ' "$H"/*.mdbefore concluding absence. Extend a hit; never re-file it. 3.45. Duplicate issue gate, chained so a refusal cannot be skipped:python3 skills/proactive-loop/scripts/gh-duplicate-check.py --repo <owner/name> --title "<title>" && gh issue create --repo <owner/name> --title "..." --body-file <f>(0 no candidate · 1 do not file, candidates named · 2 cannot answer). 3.5. Policy.python3 skills/proactive-loop/scripts/self-development-enabled.py→disabledskips 4–8, 10, 11. Owner-requested tasks, pending questions, health/service recovery and the watcher remain active. Manual/proactive-loopinvocation does not override the policy. 3.6. Tool suites.python3 skills/proactive-loop/scripts/tool-suites-check.py --workspace "$WORKSPACE" --repo "$PWD"(0 pass · 1 a suite failed · 2 cannot answer). Extra suites are declared in$WORKSPACE/hosts/<host>/tool-suites-extra.json. It passes no argv to a suite. - Build log. Read
$WORKSPACE/build_log.md; do not rebuild what works. - Pick the highest-ROI unblocked item: owner tasks and blockers, then peer
opinion-requested/review-requestedclaims in #bot2bot, then voice reliability, then regressions, then the menu. Write the pick into the statusstep. - Act. A blocked primary is a cue to switch lanes, never to idle. Before pivoting from the owner's
latest ask, read
state/last-owner-activity.jsonand announce the pivot in the bot-to-bot channel perPERSONAL_CLAUDE.md. Skip this step only for: MINIMAL tier; owner active in the last ~5 min;state/presenter-mode.sentinel(bash scripts/presenter-mode.sh);state/loop-paused-until.sentinel;python3 src/shutdown.py checkexiting 0 (finish in hand, write idle, do not relaunch). 6.5. Idle surface. Record the pass:python3 skills/proactive-loop/scripts/idle-surface-hash.py --state "$WORKSPACE/state/idle-streak.json" --pass-outcome substantive|noop. The held set is edited only throughpython3 skills/proactive-loop/scripts/idle-held.py --state "$WORKSPACE/state/idle-streak.json" --remove <id> --reason "<why>" --add <id>:<gate> --note <owner/repo#n>(no whole-list interface; a removal needs a reason); audit notes with--audit-notes "$PWD"and retire merged items. Compute:idle-held.py … | idle-surface-hash.py --state …→post <hash>orquiet <hash>. Onpost: send ONE FYI line to the owner's primary channel, THEN re-run the same pipe with--writeonidle-held.pyAND--commitonidle-surface-hash.py— each flag belongs to its own side, and--commitalone leaves added holds, removal reasons and notes unpersisted, so the next pass re-posts the stale hold. Never commit before the send; never build the list from recall.quiet+ owner active in the last ~30 min → still drop a one-line activity signal. 6.7. Failure closure. Every reported failure ends with the mechanism that prevents its recurrence, linked, or the sentence "no mechanism exists, because X". A filed lesson is not a third option. - Build log write. Append with
O_APPENDand a random marker; assertcount(MARK) == 1by reading the file back. Never read-modify-replace. Then decide whether arelay/relay-<ts>.mdnote is owed (a PR event, a resolved question, a lifted or new blocker, a judgment) — most passes owe none. 7.5. Memory index, chained so a refusal cannot be skipped:python3 skills/proactive-loop/scripts/memory-index-budget.py --adding "<row>" && <append the row>(0 safe · 1 refuse, casualty named · 2 cannot answer). On refusal free room FIRST and check the row is still reachable from its hub before removing it; which rows go is the owner's call. - Ask.
python3 scripts/ask-owner.py "<question>" [--context "<why / options>"] [--task-file <workspace>/tasks/<task>.txt]— never hand-edit. It records the row in the owner's Pending questions database (the outbox holds it while the room is unreachable), queues the question to the owner (an owner-DM task's conversation, else his DM) and fires the macOS notification. Read its output: aFAILEDline is not an ask; confirm the id withpending_questions_reader.py list --json. Then pivot; never block. - Watcher. Ask for this inbox, never host-wide (on a pool host a worker's watcher satisfies any
"is a watcher running" probe):
python3 src/watcher_identity.py role-present session --inbox "$WORKSPACE/tasks" --ready "$WORKSPACE/state"(substitute$SUTANDO_TASKS_DIRfor the inbox on an instance whose tasks dir isn't<workspace>/tasks/).no→ run the launcher:Monitorbash src/watch-tasks-stream.sh --role session --inbox "$WORKSPACE/tasks"(same substitution),description: 'Streaming task watcher'. The watcher checks its own inbox at startup: if a session watcher already covers it, the new one exits 0 naming the holder, so a start is never a duplicate; over a standby it proceeds and the supervisor stands the standby down.yesorunknown→ change nothing and say so. A re-arm that printsWATCHER_HELD:on stdout did not start: it names the holder (pid, role, whether its output is read) and the--force-restartcommand; report that line and do not re-arm again.--force-restartreplaces a holder; use it only on the owner's word. Stop pids only when thetask-watcherprobe from step 3 presents owned and ownerless as two separately labelled groups; one undifferentiated list means change nothing. Never start the watcher untagged: an untagged watcher is invisible to the verdict above and to the supervisor. 9.5. PR thread gate, chained so a refusal cannot be skipped:python3 skills/proactive-loop/scripts/pr-monologue-check.py <PR url|number --repo owner/name> --me <your-login> && gh pr comment <number> --repo <owner/name> --body-file <f>(0 safe · 1 refuse, run and span named · 2 cannot answer). On refuse, re-solicit through a stand. - Discord. Check the channels in
reference_discord_channels.md; forward actionable public items to the dev channel. #bot2bot tags:claim:blocked:done:ping:nack:opinion-requested:. First PR opened wins a claim. Bots never merge. Three unresolved round-trips → both positions in oneask-owner.pyask, proceed with the cheaper-to-reverse option. - Heartbeat. Substantive pass + #bot2bot configured + other bot active →
done: <one line>via thebot2bot-postskill. Never fall back toresults/proactive-*.txt. Never writecontextual-chips.json.
What ships with it
17 files beside SKILL.md in the same directory: the scripts, references and assets a skill reads on demand. Not counted in the per-session cost; read them before you install if any of them is executable.
- manifest.json 478 B
- README.md 569 B
- scripts/check-dedup-targets.py 4.7 KB runs code
- scripts/claude-quota-cadence.py 5.3 KB runs code
- scripts/codex-auto-reset-timer.py 11 KB runs code
- scripts/codex-auto-reset.py 19 KB runs code
- scripts/codex-quota-gate.py 8.2 KB runs code
- scripts/gh-duplicate-check.py 8.9 KB runs code
- scripts/idle_state.py 2.5 KB runs code
- scripts/idle-held.py 18 KB runs code
- scripts/idle-surface-hash.py 6.8 KB runs code
- scripts/memory-index-budget.py 8.5 KB runs code
- scripts/pr-monologue-check.py 8.2 KB runs code
- scripts/quota-tier.py 7.9 KB runs code
- scripts/self-development-enabled.py 2.2 KB runs code
- scripts/tool-suites-check.py 14 KB runs code
- scripts/warn-already-triaged.py 10.0 KB runs code
What this file has done since we first saw it
Hashed on every crawl. A supply-chain change to an agent config is a question of when, not whether, so the history is kept rather than the latest state alone.
- yesterday Changed d5844af781f1
- 13d ago Changed · +2 lines bb5e964e39f0
- 17d ago Changed · +2 lines 30b92143cc50
- 20d ago Changed · +3 lines 6ae8a018a717
- 24d ago Changed · +7 lines 56e6a50ffbc1
- 25d ago Changed · +3 lines e4fad9e2d69c
- 1mo ago Changed · -1 lines 7b4984e62334
- 1mo ago Changed · +2 lines 933d8cd12f51
- 1mo ago Changed · +5 lines 8e00bc3fc3f7
- 1mo ago First seen · 116 lines · 29 tokens per session scan C 92ecdbbf4f85
proactive-loop is a skill published in the GitHub repository sonichi/sutando (397 stars, last pushed today), licensed MIT. It adds 29 tokens to every session and 3,181 once invoked, about $0.0001 per session on Opus 5.5. A static security scan graded it C with 1 finding (nullifies safety policies). No closer match exists in the catalogue, so it is treated as the original; first seen 2026-08-30.
Other skills, from other repositories
app-builder
Build and edit small, personal visual tools and artifacts — dashboards, trackers, calculators, data visualizations, charts, simple landing pages, and slide decks the user wants for THEMSELVES. This is the right skill whenever the user asks to "visualize this," "make a chart," or "build an artifact" for their own use…
gmail
Manage Gmail email — drafting, sending, organizing, filters, vacation replies, and inbox analysis.
assistant-migration
Migrate from ChatGPT, Claude, OpenClaw, Hermes, Manus, and other AI assistants into Vellum by inspecting their data exports, conversation archives, files, prompts, custom instructions, memory, saved memories, tools, GPTs, workflows, integrations, and relationships, then mapping as much as safely possible into Vellum…
guardian-verify-setup
Set up channel verification for phone, Telegram, Slack, Discord, or email channels via outbound verification flow.
stripe-link-wallet
Agent wallet on the Stripe Link CLI (link-cli). Connect the wallet, then buy, purchase and pay for things on the user's behalf via approved spend requests, one-time-use cards, and 402 / Machine Payment Protocol (MPP) payments.
media-processing
Ingest and process media files (video, audio, image).