proactive-loop

proactive-loop is a skill for Claude Code from sonichi/sutando. It costs 29 tokens per session (3,181 once invoked), scanned C, original, MIT.

A recurring autonomous work loop for Sutando that checks tasks and system health, chooses work, performs maintenance or builds missing capabilities, and records each pass.

In plain words
What is it for?
Watching for new tasks, running health checks, maintaining or extending the system, and repeating the work at a chosen interval.
Why use it?
It keeps routine monitoring and follow-up work running on a schedule rather than waiting for a person to start every check.

Skill for Claude Code

Written for Claude Code: user-invocable in frontmatter. Also seen: mentions Claude Code; mentions Codex.

Good fit Watching for new tasks, running health checks, maintaining or extending the system, and repeating the work at a chosen interval.

Compare 6 skills from other repositories ↓
Install with agentmods
npx agentmods add skills/sonichi/sutando/proactive-loop
Install

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.

Any agent
npx skills add sonichi/sutando --skill proactive-loop
Clone the repo
git clone --depth 1 https://github.com/sonichi/sutando

Made for: Claude Code.

Wrote 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.

agentmods badge for proactive-loop

README.md
[![agentmods](https://agentmods.dev/badge/skills/sonichi/sutando/proactive-loop/github.svg)](https://agentmods.dev/skills/sonichi/sutando/proactive-loop)
Your own site
<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.

agentmods 80×15 button for proactive-loop

Your own site · 80×15
<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>
Per session 29 Skills are progressive disclosure: only the name and description are preloaded; the body loads when the skill is used.
When invoked 3,181 The whole file, excluding the scripts and references it only reads on demand.
Security scan C 1 finding. A grade says what 26 rules found in the file — not that it is safe.
Origin original No closer match found in the catalogue.
Token cost

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.

ModelPer sessionOnce 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

Measured yesterday against content hash d5844af781f1, method: parsed. Prices are Anthropic first-party input rates as of 2026-10-07, from the pricing page.

Security

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.

The scan reads SKILL.md. This mod also ships 15 executable files (scripts/check-dedup-targets.py, scripts/claude-quota-cadence.py, scripts/codex-auto-reset-timer.py, …), listed below but not scanned — reading those needs a real analyzer, not pattern matching.

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.
skills/proactive-loop/SKILL.md · 139 lines

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

  1. /schedule-crons — registers the session crons and stamps them.
  2. Task watcher via the Monitor tool: command: 'bash src/watch-tasks-stream.sh --role session --inbox "$(bash scripts/sutando-config.sh workspace)/tasks"' (substitute $SUTANDO_TASKS_DIR for the inbox when it is set — the same tag step 9's re-arm uses), timeout_ms: 1800000, description: 'Streaming task watcher'. Each TASK_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 as exit code 144); the inbox is unwatched until the standby's grace elapses. Monitor has no persistent option: it kills the command at timeout_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 no Monitor tool: src/startup.ps1 owns src/task-dispatcher.ps1; do not start another watcher.
  3. If CronList already shows a main-loop / /proactive-loop job, 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.

  1. 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 …). Then python3 skills/proactive-loop/scripts/claude-quota-cadence.py --json → if effective_cron differs from the /proactive-loop job in CronList: capture the old job id, CronCreate the new job with prompt: "/proactive-loop" and cron: <effective_cron>, confirm it in CronList. Then CronDelete the old id and confirm exactly one /proactive-loop job 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 the context-reconstruct skill (a Skill-tool call, not a mention). It reads <workspace>/hosts/<host>/current-track.md first, then the live thread (python3 src/discord-read.py <channel> --serving <channel> when serving a task, --operator otherwise), pending questions, relay, build log. Trust the record over recall; maintain current-track.md.
  2. 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>" then python3 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 to src/result_markers.py; never re-implement them. When this core consumes a task itself, move $WORKSPACE/tasks/<id>.txt to $WORKSPACE/tasks/archive/<id>.txt after 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 rearm restarts the waiter of any pending connector wait that lost it; idempotent, and a failure never blocks the pass.
  3. Questions. Nothing surfaces on a pass: a question reaches the owner once, when asked (scripts/ask-owner.py); src/check-pending-questions.py --notify reminds only when he asks, flagless it files what the outbox holds, sends nothing. src/pending_questions_reader.py list only when he asks or you are blocked on an answer.
  4. Health. python3 src/health-check.py; fix with --fix what it can. A warn is a pointer into the record: before investigating, grep -in "<entity from the warn TEXT>" "$H/current-track.md" and pending_questions_reader.py list --json | grep -i "<entity>" with H="$WORKSPACE/hosts/$(bash scripts/sutando-config.sh host-label)"; a zero means try another token, then grep -n '^## ' "$H"/*.md before 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 → disabled skips 4–8, 10, 11. Owner-requested tasks, pending questions, health/service recovery and the watcher remain active. Manual /proactive-loop invocation 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.
  5. Build log. Read $WORKSPACE/build_log.md; do not rebuild what works.
  6. Pick the highest-ROI unblocked item: owner tasks and blockers, then peer opinion-requested / review-requested claims in #bot2bot, then voice reliability, then regressions, then the menu. Write the pick into the status step.
  7. 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.json and announce the pivot in the bot-to-bot channel per PERSONAL_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 check exiting 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 through python3 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> or quiet <hash>. On post: send ONE FYI line to the owner's primary channel, THEN re-run the same pipe with --write on idle-held.py AND --commit on idle-surface-hash.py — each flag belongs to its own side, and --commit alone 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.
  8. Build log write. Append with O_APPEND and a random marker; assert count(MARK) == 1 by reading the file back. Never read-modify-replace. Then decide whether a relay/relay-<ts>.md note 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.
  9. 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: a FAILED line is not an ask; confirm the id with pending_questions_reader.py list --json. Then pivot; never block.
  10. 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_DIR for the inbox on an instance whose tasks dir isn't <workspace>/tasks/). no → run the launcher: Monitor bash 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. yes or unknown → change nothing and say so. A re-arm that prints WATCHER_HELD: on stdout did not start: it names the holder (pid, role, whether its output is read) and the --force-restart command; report that line and do not re-arm again. --force-restart replaces a holder; use it only on the owner's word. Stop pids only when the task-watcher probe 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.
  11. 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 one ask-owner.py ask, proceed with the cheaper-to-reverse option.
  12. Heartbeat. Substantive pass + #bot2bot configured + other bot active → done: <one line> via the bot2bot-post skill. Never fall back to results/proactive-*.txt. Never write contextual-chips.json.

Read the full file on GitHub · 139 lines

Changes

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.

  1. yesterday Changed d5844af781f1
  2. 13d ago Changed · +2 lines bb5e964e39f0
  3. 17d ago Changed · +2 lines 30b92143cc50
  4. 20d ago Changed · +3 lines 6ae8a018a717
  5. 24d ago Changed · +7 lines 56e6a50ffbc1
  6. 25d ago Changed · +3 lines e4fad9e2d69c
  7. 1mo ago Changed · -1 lines 7b4984e62334
  8. 1mo ago Changed · +2 lines 933d8cd12f51
  9. 1mo ago Changed · +5 lines 8e00bc3fc3f7
  10. 1mo ago First seen · 116 lines · 29 tokens per session scan C 92ecdbbf4f85

Subscribe to this mod's changes

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.

Related

Other skills, from other repositories