agent-activity
Streams what the agent is doing into the room, as rows the desktop client renders in an **events drawer** above the composer (collapsed: avatar, pulsing dots,…
Single entry point for fresh-session bootstrap. Runs optional task-orphan recovery, cron registration, and watcher start in a fixed order. Replaces the current `claude -- '/schedule-crons'` invocation pattern as the canonical CLI startup target.
$ npx -y skills add sonichi/sutando --skill startup --agent claude-codeHow it fires
How this skill gets triggered: by you, by Claude, or both.
/startupContext preview
The summary Claude sees to decide when to auto-load this skill.
Single entry point for fresh-session bootstrap. Runs optional task-orphan recovery, cron registration, and watcher start in a fixed order. Replaces the current `claude -- '/schedule-crons'` invocation pattern as the canonical CLI startup target.
name: startup description: "Single entry point for fresh-session bootstrap. Runs optional task-orphan recovery, cron registration, and watcher start in a fixed order. Replaces the current `claude -- '/schedule-crons'` invocation pattern as the canonical CLI startup target." user-invocable: true
The canonical entry point for a fresh Sutando session. Bundles every action that must happen once at session start, in the correct order.
**Usage**: `/startup`
ARGUMENTS: $ARGUMENTS — `--worker` selects the worker bootstrap below; empty is the canonical core.
A pool worker is an instance, not the canonical core. It shares the host's workspace but owns exactly one thing: the watcher on its own delivery folder. **When `$ARGUMENTS` contains `--worker`, run ONLY the sequence in this section and none of the steps below it** — no orphan check (the core owns `tasks/`), no `/schedule-crons` invocation, no ceremony gate (it stamps the core's `schedule-crons-stamp.json`), and no `/startup complete` line. The one exception is step 2.5 below: a `crons.json` entry explicitly pinned to THIS worker's own id (via its `owner` field, see `skills/schedule-crons/SKILL.md`) is this worker's to register — that is not "a second registrant" for it, because `/schedule-crons` skips any entry owned by a worker (`src/cron_ownership.py`). Every entry without an `owner`, or owned by a different worker, stays untouched here.
1. Ask whether this instance's own watcher is already live. **The core's step 1.5 gate is the wrong question here** — it is satisfied by *any* watcher tree on the host, and the core's own always satisfies it, so a worker that consults it never starts the watcher it exists to run:
"${SUTANDO_PY:?the launcher forwards the resolved interpreter}" "$SUTANDO_WORKER_BOOTSTRAP"The gate belongs to the optional `worker-pool` skill, not to this one, so it is **named by the spawner in the session's env** and never spelled as a path here — a core install without that skill must still boot. If `$SUTANDO_WORKER_BOOTSTRAP` is unset or names no file, treat it as `unknown`: say so and start nothing.
It answers about THIS instance's sentinel (`util_paths.watcher_sentinel_path`, the same file the watcher stamps) in the assigned workspace — read from the `SUTANDO_WORKSPACE_DIR` variable the spawner sets and the watcher honours, so gate and watcher can never inspect two trees — and prints one word: `start`, `skip`, or `unknown`.
2. On `start` only, start the streaming watcher via the `Monitor` tool — `command: 'bash "$SUTANDO_WATCHER_CMD" "$SUTANDO_TASKS_DIR"'`, `persistent: true`. Both are absolute and come from the launcher, because this session's cwd is the spawner's `--cwd` and need not be the repo — a relative `src/watch-tasks-stream.sh` exits 127 there. If `$SUTANDO_WATCHER_CMD` is unset you were not launched as a worker: stop and say so rather than guessing a path.
2.5. **On `start` only** (same gate as step 2 — a fresh incarnation; a `skip` means this instance is already running and re-registering here would duplicate whatever it already has), register any `crons.json` entries pinned to THIS worker's own id. There is no in-session memory of a prior registration to compare against the way `/schedule-crons` step 3 has for a mid-session re-run, so this only ever needs to handle the fresh-boot case:
REPO="$(cd "$(dirname "$SUTANDO_WATCHER_CMD")/.." && pwd)"
H="$(bash "$REPO/scripts/sutando-config.sh" host-label)"
CF="$SUTANDO_WORKSPACE_DIR/hosts/$H/crons.json"
"$SUTANDO_PY" -c "
import json, sys
sys.path.insert(0, '$REPO/src')
from cron_ownership import entries_for_owner
try:
cfg = json.load(open('$CF'))
except FileNotFoundError:
cfg = []
print(json.dumps(entries_for_owner(cfg, '$SUTANDO_INSTANCE_ID')))"The repo root is derived from `$SUTANDO_WATCHER_CMD` rather than assumed from cwd, for the same reason step 2 does. For each entry the filter returns, `CronCreate` it exactly as `/schedule-crons` step 3 would (`prompt_skill` → `/skill-name`; otherwise the `prompt` string) — an entry pinned to a worker is never a `monitor`, `execution: "codex-task"`, or `launchd: true` entry (those ownership models are core-only), so no further filtering is needed. If `crons.json` doesn't exist, or nothing is pinned to `$SUTANDO_INSTANCE_ID`, there is nothing to do here — that is the common case for most workers.
3. Report what actually happened, never a fixed line: `start` → `worker <instance> ready: watching <inbox>` (plus `+ N cron(s) registered` when step 2.5 registered any); `skip` → `worker <instance> already watching <inbox>` (nothing was started); `unknown` → start NOTHING and report the gate's `why=` verbatim. Reporting readiness after an `unknown` is the failure this step exists to prevent: it claims a watcher that does not exist.
Previously: `claude -- "/schedule-crons"` was the de-facto startup invocation, and `skills/schedule-crons/SKILL.md` accumulated startup ceremony (cron-fallback, watcher) on top of its actual job (registering crons from `crons.json`).
Now: `claude -- "/startup"` is the canonical startup target. `/startup` orchestrates the sequence; `/schedule-crons` shrinks back to its narrow job.
Migration: update `~/Library/LaunchAgents/*.plist` and any CLI invocation scripts to call `/startup` instead of `/schedule-crons`. `/schedule-crons` still works standalone (for manual cron re-registration) — both paths are idempotent.
Per Chi 2026-05-23 Discord: "we can make a new skill and include everything we need at start." Five rationales:
1. **Single entry point** — no more "which skill does the CLI invoke?" The launchd plist points at `/startup` and only at `/startup`. 2. **Ordering encoded in one place** — the sequence (recover state → register schedules → start watcher) lives in this skill's `On Activation`
My AI Stand — Realtime by Day, Rewriting Itself by Night. Summon my AI superpower. Voice, vision, screen, meetings, calls when I'm engaged. Learns my patterns, ships its own code when I'm not. Runs across my Macs, interacts with people & their Stands.
Repo: sonichi/sutando
Streams what the agent is doing into the room, as rows the desktop client renders in an **events drawer** above the composer (collapsed: avatar, pulsing dots,…
Local Agent Registry — a standalone, dependency-free service that tracks running Claude Code (and other) agent instances. Agents self-register on startup and…
**Prefer the `ag2-space` MCP tools when they are connected and the room exposes them** — availability is per-room and per-actor, so check…
Deterministic final-answer normalizer — a last-step pass for any task that ends in a *precise* answer (a number, a short string, a comma-list). Applies the…
Transcribes audio files and voice notes to text via Gemini 2.5-flash. Integrates with Slack, Discord, and Telegram bridges so voice clips surface as readable…
Act back on the owner's Bee wearable — the TOOL half of the Bee integration (channels-vs-tools split). The Bee CHANNEL (ag2-sparrow's `sources/bee.py` watcher)…