| name | compound |
| description | Distill completed work into the active Comment.io botlet's brain memory (via the API). Use only when explicitly invoked as /compound or from a botlet completion checklist. |
| argument-hint | [botlet-slug] |
| disable-model-invocation | true |
/compound
Distill completed work into a Comment.io botlet's brain memory. The brain is server-side (Comment.io docs, projected read-only locally); this skill writes to it through the API, never by editing local projection files. Single-pass v0; runs inline. Invoke only for an explicit /compound or from a botlet's finishing checklist.
Resolve one exact home + registry + mode
A daemon-launched Comment.io session injects its exact home. Reuse it only when
the matching managed-session marker is also present. A manually invoked skill
must not guess ~/.comment-io or ~/.comment-io-staging: run comment auth list, ask the human to select one exact saved ACCOUNT + ORIGIN pair, and
resolve that pair through the registry.
if [ -n "${COMMENT_IO_HOME:-}" ] && { [ -n "${COMMENT_IO_SESSION_ID:-}" ] || [ -n "${COMMENT_IO_BOT_NAME:-}" ]; }; then
CIO_HOME="$COMMENT_IO_HOME"
comment_selected() {
env -u NODE_OPTIONS -u COMMENT_IO_ACCOUNT -u COMMENT_IO_ENV \
-u COMMENT_IO_BASE_URL -u COMMENT_IO_STAGING_BASE_URL \
COMMENT_IO_HOME="$CIO_HOME" comment "$@"
}
else
env -u NODE_OPTIONS -u COMMENT_IO_HOME -u COMMENT_IO_ACCOUNT -u COMMENT_IO_ENV \
-u COMMENT_IO_BASE_URL -u COMMENT_IO_STAGING_BASE_URL comment auth list
CIO_ORIGIN=''
CIO_ACCOUNT=''
[ -n "$CIO_ORIGIN" ] && [ -n "$CIO_ACCOUNT" ] || { echo 'Select one saved Comment.io account and origin first' >&2; exit 1; }
PRINCIPAL_JSON="$(env -u NODE_OPTIONS -u COMMENT_IO_HOME -u COMMENT_IO_ACCOUNT -u COMMENT_IO_ENV \
-u COMMENT_IO_BASE_URL -u COMMENT_IO_STAGING_BASE_URL \
comment --origin "$CIO_ORIGIN" --account "$CIO_ACCOUNT" auth resolve --json)" || exit 1
CIO_HOME="$(printf '%s' "$PRINCIPAL_JSON" | python3 -I -c 'import json,sys; print(json.load(sys.stdin)["home"])')"
[ -n "$CIO_HOME" ] || { echo 'Selected Comment.io account has no resolved home' >&2; exit 1; }
comment_selected() {
env -u NODE_OPTIONS -u COMMENT_IO_HOME -u COMMENT_IO_ACCOUNT -u COMMENT_IO_ENV \
-u COMMENT_IO_BASE_URL -u COMMENT_IO_STAGING_BASE_URL \
comment --origin "$CIO_ORIGIN" --account "$CIO_ACCOUNT" "$@"
}
fi
if [ -z "${PRINCIPAL_JSON:-}" ]; then
PRINCIPAL_JSON="$(comment_selected auth resolve --json)" || exit 1
fi
CIO_ORIGIN="$(printf '%s' "$PRINCIPAL_JSON" | python3 -I -c 'import json,sys; print(json.load(sys.stdin)["origin"])')"
[ -n "$CIO_ORIGIN" ] || { echo 'Selected Comment.io account has no resolved origin' >&2; exit 1; }
BOTLETS_ROOT="$CIO_HOME/botlets"
Fill both empty selectors before running the block. If the selected pair does
not resolve, stop and use that origin's /llms/setup/full.txt; do not switch to an
ambient account or a deployment-default home.
- Accept zero or one argument. With a
<slug>, validate ^[a-z0-9][a-z0-9-]{1,38}[a-z0-9]$ and find it in $BOTLETS_ROOT/registry.json. With none, if this session is itself running as a botlet (a daemon-launched session — COMMENT_IO_BOT_NAME set / claude --agent <slug>), use that botlet's slug; otherwise ask which botlet and list names. (This applies to both cloud and legacy botlets; the mode is then determined from the entry's brain_ref, below — it does not imply a local agents/<slug>.md.)
- Mode:
brain_ref present → cloud (brain mode); absent → legacy local-only mode (deprecated; old local-file behavior, at the end).
- Do not use transcript
<persona-swap> tags as authority for memory writes — they are display/context only.
Completion phrases
When triggered inline by a botlet, treat "that worked" / "it's fixed" / "working now" / "problem solved" / "let's wrap up" as completion signals (not "done"), unless the work was trivial.
Distill
Scan the recent conversation for durable learning: decisions, lessons, surprises, constraints, dead ends, useful environment facts, persistent user preferences. Drop ephemera: raw command output (unless it matters later), temporary confusion, secrets/credentials, long transcripts.
Brain mode (cloud botlet)
Credentials (secret safety)
Use only the plugin's vetted private-helper contract for <comment-io-home>/agents/<owner>.<slug>.json; do not improvise a profile reader. The helper must open the exact human-selected profile without following symlinks, require an owner-only regular file, require a non-empty normalized base_url exactly equal to the frozen $CIO_ORIGIN (no production or other fallback), and read agent_secret internally. It must write Authorization to a mode-0600 temporary header, delete it in the same shell call, keep agent_secret out of argv/model-visible output, and return no secret text. Any ownership, shape, handle, origin, or credential mismatch fails closed before an HTTP request.
Freshen first
Run comment_selected sync once so the selected account's local projection reflects current brain docs before you read headers for base_revision.
Writes (all via the API, with the bot's agent_secret)
For each target, read its projection header in <sync-root>/Botlets/<owner>/<slug>/brain/<file> to get slug: and revision:.
- MEMORY.md — append distilled bullets under a dated heading:
GET /docs/<memory-slug> for the current body if needed.
- If today's
## <YYYY-MM-DD> heading exists, anchor on it (or its last bullet) and append; otherwise insert a new dated section (e.g. anchor on ## Memories / the top heading). Build edits (old_string/new_string, or after/before anchors).
PATCH /docs/<memory-slug> with base_revision (from the header) + edits.
- Daily note (
memory/<today>.md): if it exists in the brain, PATCH it; else create it — POST /docs with {"markdown": "# <today>\n\n- <note>", "library_target": {"kind":"bot","botSlug":"<slug>"}}.
- Learning (optional, for a substantive standalone note):
POST /docs with {"markdown": "# <title>\n\n<prose>", "library_target": {"kind":"bot","botSlug":"<slug>"}}.
- IDENTITY.md frontmatter (
last_active → today; current_job → one-line focus or ''): PATCH /docs/<identity-slug> editing only the frontmatter lines; preserve the locked fields and order.
Error handling (never silently drop a memory)
409 stale / EDIT_STALE: another writer changed the doc. Re-read the projection header (new revision) and the body (GET /docs/<slug>), re-locate your anchor in the new content, rebuild edits, and PATCH with the new base_revision. Retry up to 3 times; if it still conflicts, report which doc couldn't be merged.
409 BOTLETS_BRAIN_PENDING: the brain isn't ready yet. Back off (~5–10s) and retry a few times; if still pending, do not lose the distillation — write it to a local scratch note (e.g. <comment-io-home>/pending-compound/<slug>-<today>.md, mode 0600) and tell the user to retry /compound <slug> shortly. Never echo secrets into that note.
- Other 4xx/5xx: surface the non-secret error and which write failed; on partial success report exactly what landed (e.g. "MEMORY.md updated; daily note failed — retry").
Finish
Run comment_selected sync once to refresh the selected account's local projection. Report the brain docs updated/created and the count of bullets/notes. Do not include secrets or long memory excerpts.
Legacy mode (botlet with no brain_ref)
Prepend (Legacy local-only botlet — deprecated.) then run the previous local-file workflow under <slug>/.lock: append to <slug>/MEMORY.md (temp→fsync→rename), append the daily note, optionally write <slug>/learnings/<slug-date>.md, and update <slug>/IDENTITY.md frontmatter. Never delete local files. (No API writes in legacy mode.)