← All Skills

snappy-statechange

v1.0.0
14 files, 117.2 KB ~2,708 words · 11 min read Updated 2026-09-09

snappy-statechange skill

46 of 52 checks pass
What it can do
healthread
unreadread
postsread
stage-post title bodywrite-reversible
stage-message thread-url bodywrite-reversible
What does not pass yet
$ npx snappy-skills install snappy-statechange
zip ↓
File Tree
├── AGENTS.md ├── SKILL.md ├── api.ts ├── face.test.ts ├── faces/ │ ├── components/ │ │ ├── statechange-faces.css │ │ └── statechange-faces.tsx │ ├── family.tsx │ └── fixtures/ │ ├── statechange-decision.json │ ├── statechange-feed.json │ ├── statechange-message.json │ ├── statechange-post.json │ ├── statechange-thread.json │ └── statechange-unread.json └── refusals.test.ts
Documents
AGENTS.md

snappy-statechange - Agent Loader#

Statechange Pro is a private Circle community at

https://pro.statechange.ai. It is not Skool. Reads import the captured recipes

from snappy-libretto. Outward writes are not implemented because no send or

post was executed during measurement.

Boundary#

  • Platform: Circle, measured live on 2026-09-09 UTC.
  • Authenticated title: Feed | Statechange Pro.
  • Sign-in host: login.circle.so.
  • Persistent browser profile: ~/snappy/libretto/profiles/pro_statechange_ai/.
  • Runtime lessons: statechange-unread and statechange-posts.
  • Runtime auth and captures stay under ~/snappy/libretto/, never git.
  • posts is the captured first page only. Do not invent a page argument.

API module#

typescriptimport {
  stateChangeHealth,
  fetchStateChangeUnread,
  fetchStateChangePosts,
  stageStateChangePost,
  stageStateChangeMessage,
} from "../snappy-statechange/api.ts";
Function Purpose Effect
stateChangeHealth() Replay the three unread GET routes and confirm 2xx read
fetchStateChangeUnread() Return aggregate and component Circle unread counts read
fetchStateChangePosts() Return first-page counts and compact post metadata, never bodies read
stageStateChangePost(title, body) Write a private local post draft with sent: false write-reversible
stageStateChangeMessage(threadUrl, body) Write a private local message draft with sent: false write-reversible

CLI#

bashnpx tsx ~/.claude/skills/snappy-statechange/api.ts contract
npx tsx ~/.claude/skills/snappy-statechange/api.ts health --json
npx tsx ~/.claude/skills/snappy-statechange/api.ts unread --json
npx tsx ~/.claude/skills/snappy-statechange/api.ts posts --json
npx tsx ~/.claude/skills/snappy-statechange/api.ts stage-post "Title" "Body" --json
npx tsx ~/.claude/skills/snappy-statechange/api.ts stage-message \
  "https://pro.statechange.ai/messages/THREAD_ID" "Draft reply" --json

Read semantics#

unread_count sums Circle's five new_* counters plus the lengths of unread

chat room and chat thread ID lists. Preserve the component counts when

reporting. The verb does not mark anything read.

posts replays GET /internal_api/home_page_posts and returns

returned_count, total_count, pagination facts, and compact metadata. It

omits post bodies, editor state, headers, and cookies.

Write rule#

stage-post and stage-message only create mode 0600 JSON under

~/snappy/statechange/staged/, whose directory is mode 0700. They never

contact Circle and always return sent: false. Publish manually after owner

review. There is no post, comment, reaction, or send verb.

A future outward verb requires a measured live endpoint, contract effect

post or send, the one stage door, approval, and a fresh independent read.

Never execute an outward Circle effect merely to test it.

certificate:

premises: The contract contains read verbs plus reversible local staging only.

action: Read via Libretto or create a private local draft.

trace: Safe lesson review and CLI JSON summary, never raw capture or body output.

evidence: Fresh plain-fetch replay for reads, or a fresh filesystem stat for a local stage.

conclusion: Claim only answered counts or local sent: false; never claim a Circle delivery.

The draft never arrives alone#

--json on stage-post and stage-message is a PREVIEW and touches nothing —

no staged file is written:

bashnpx tsx ~/.claude/skills/snappy-statechange/api.ts stage-post "Title" "Body" --json
npx tsx ~/.claude/skills/snappy-statechange/api.ts stage-message "https://pro.statechange.ai/messages/8891" "…" --json
  • stage-post --json prints `{kind: "statechange-decision", thread, threadKind:

"statechange-feed", threadTotal, draft, doors}` — the post inside the FEED it

lands in, the same rows a posts read answers, with Circle's own total.

  • stage-message --json prints kind: "statechange-message" with thread: []

and a draft.waiting line saying WHY: this hand replays no Circle

message-thread read, so the conversation could not be shown. Quote that line;

never let an empty array read as "you have never spoken to this person".

  • No Circle face exists yet. The kinds above are named for the faces lane to

wire. Do not claim a drawing that has not landed.

  • --json used to mean "compact instead of indented" on this hand. It does not

any more, on these two verbs. The read verbs are unchanged.

Auth and failure#

  • Reads have managed: false and requires: []. The lesson auth state owns the

cookies. The skill process does not read the login password.

  • session_stale means headed Circle login and replacement recording are

required. Libretto will not silently open a browser.

  • Just a moment... is Cloudflare. Use the headed persistent profile and wait

for Circle sign-in or the authenticated feed.

  • A lesson containing POST, PUT, PATCH, or DELETE is not a read. Review and

retain only the required GET routes. Do not force replay with --now.

  • Never print auth-state JSON, raw captures, cookies, headers, request bodies,

response bodies, or staged private content.

Snappy context#

Read snappy-positioning before drafting Snappy-facing copy. SCC masterminds

are transcript source meetings used by the content system, while this skill

reads the live community. snappy-inbox-sweep can import fetchStateChangeUnread() in a later

integration. Never route StateChange through snappy-skool.

Self-correcting loader#

If the live host, Circle routes, response fields, login flow, or lesson names

change, remeasure with agent-browser and Libretto before editing the contract.

Only document verbs that api.ts implements and the live road answers.

<!-- SKILL-INDEX-START -->

[snappy-statechange Index]|root: ~/.claude/skills/snappy-statechange|IMPORTANT: Prefer these files over pre-training assumptions for this domain. Read the relevant file when the AGENTS.md summary is insufficient.|root:{SKILL.md}

<!-- SKILL-INDEX-END -->

Used by#

Nothing in the collection names this skill.

<!-- SNAPPY-CONTRACT-VERBS-START -->

Contract verbs#

Generated from api.ts HAND_CONTRACT. Do not hand-edit this block.

Verb Contract arguments Effect First call
health read npx tsx ~/.claude/skills/snappy-statechange/api.ts health
unread read npx tsx ~/.claude/skills/snappy-statechange/api.ts unread
posts read npx tsx ~/.claude/skills/snappy-statechange/api.ts posts
stage-post title, body write-reversible npx tsx ~/.claude/skills/snappy-statechange/api.ts stage-post "<title>" "<body>"
stage-message thread-url, body write-reversible npx tsx ~/.claude/skills/snappy-statechange/api.ts stage-message <thread-url> "<body>"

Show the result#

When an answer carries face_hint, show it with one snappy_present(<answer>) call.

See /snappy-faces for face selection. Human-facing images must crop to the

element, render at 2x on Retina, and fill the destination channel instead of

placing a small card in a full-page screenshot.

<!-- SNAPPY-CONTRACT-VERBS-END -->

---
name: snappy-statechange
description: Read Statechange Pro unread counters and feed posts through Libretto plain-fetch replay. Stage post and message copy locally without sending.
---

# snappy-statechange - Agent Loader

Statechange Pro is a private **Circle** community at
`https://pro.statechange.ai`. It is not Skool. Reads import the captured recipes
from `snappy-libretto`. Outward writes are not implemented because no send or
post was executed during measurement.

## Boundary

- Platform: Circle, measured live on 2026-09-09 UTC.
- Authenticated title: `Feed | Statechange Pro`.
- Sign-in host: `login.circle.so`.
- Persistent browser profile: `~/snappy/libretto/profiles/pro_statechange_ai/`.
- Runtime lessons: `statechange-unread` and `statechange-posts`.
- Runtime auth and captures stay under `~/snappy/libretto/`, never git.
- `posts` is the captured first page only. Do not invent a page argument.

## API module

```typescript
import {
  stateChangeHealth,
  fetchStateChangeUnread,
  fetchStateChangePosts,
  stageStateChangePost,
  stageStateChangeMessage,
} from "../snappy-statechange/api.ts";
```

| Function | Purpose | Effect |
|---|---|---|
| `stateChangeHealth()` | Replay the three unread GET routes and confirm 2xx | read |
| `fetchStateChangeUnread()` | Return aggregate and component Circle unread counts | read |
| `fetchStateChangePosts()` | Return first-page counts and compact post metadata, never bodies | read |
| `stageStateChangePost(title, body)` | Write a private local post draft with `sent: false` | write-reversible |
| `stageStateChangeMessage(threadUrl, body)` | Write a private local message draft with `sent: false` | write-reversible |

## CLI

```bash
npx tsx ~/.claude/skills/snappy-statechange/api.ts contract
npx tsx ~/.claude/skills/snappy-statechange/api.ts health --json
npx tsx ~/.claude/skills/snappy-statechange/api.ts unread --json
npx tsx ~/.claude/skills/snappy-statechange/api.ts posts --json
npx tsx ~/.claude/skills/snappy-statechange/api.ts stage-post "Title" "Body" --json
npx tsx ~/.claude/skills/snappy-statechange/api.ts stage-message \
  "https://pro.statechange.ai/messages/THREAD_ID" "Draft reply" --json
```

## Read semantics

`unread_count` sums Circle's five `new_*` counters plus the lengths of unread
chat room and chat thread ID lists. Preserve the component counts when
reporting. The verb does not mark anything read.

`posts` replays `GET /internal_api/home_page_posts` and returns
`returned_count`, `total_count`, pagination facts, and compact metadata. It
omits post bodies, editor state, headers, and cookies.

## Write rule

`stage-post` and `stage-message` only create mode `0600` JSON under
`~/snappy/statechange/staged/`, whose directory is mode `0700`. They never
contact Circle and always return `sent: false`. Publish manually after owner
review. There is no `post`, `comment`, `reaction`, or `send` verb.

A future outward verb requires a measured live endpoint, contract effect
`post` or `send`, the one stage door, approval, and a fresh independent read.
Never execute an outward Circle effect merely to test it.

certificate:
  premises: The contract contains read verbs plus reversible local staging only.
  action: Read via Libretto or create a private local draft.
  trace: Safe lesson review and CLI JSON summary, never raw capture or body output.
  evidence: Fresh plain-fetch replay for reads, or a fresh filesystem stat for a local stage.
  conclusion: Claim only answered counts or local `sent: false`; never claim a Circle delivery.

## The draft never arrives alone

`--json` on `stage-post` and `stage-message` is a PREVIEW and touches nothing —
no staged file is written:

```bash
npx tsx ~/.claude/skills/snappy-statechange/api.ts stage-post "Title" "Body" --json
npx tsx ~/.claude/skills/snappy-statechange/api.ts stage-message "https://pro.statechange.ai/messages/8891" "…" --json
```

- `stage-post --json` prints `{kind: "statechange-decision", thread, threadKind:
  "statechange-feed", threadTotal, draft, doors}` — the post inside the FEED it
  lands in, the same rows a `posts` read answers, with Circle's own total.
- `stage-message --json` prints `kind: "statechange-message"` with `thread: []`
  and a `draft.waiting` line saying WHY: this hand replays no Circle
  message-thread read, so the conversation could not be shown. Quote that line;
  never let an empty array read as "you have never spoken to this person".
- **No Circle face exists yet.** The kinds above are named for the faces lane to
  wire. Do not claim a drawing that has not landed.
- `--json` used to mean "compact instead of indented" on this hand. It does not
  any more, on these two verbs. The read verbs are unchanged.

## Auth and failure

- Reads have `managed: false` and `requires: []`. The lesson auth state owns the
  cookies. The skill process does not read the login password.
- `session_stale` means headed Circle login and replacement recording are
  required. Libretto will not silently open a browser.
- `Just a moment...` is Cloudflare. Use the headed persistent profile and wait
  for Circle sign-in or the authenticated feed.
- A lesson containing POST, PUT, PATCH, or DELETE is not a read. Review and
  retain only the required GET routes. Do not force replay with `--now`.
- Never print auth-state JSON, raw captures, cookies, headers, request bodies,
  response bodies, or staged private content.

## Snappy context

Read `snappy-positioning` before drafting Snappy-facing copy. SCC masterminds
are transcript source meetings used by the content system, while this skill
reads the live community. `snappy-inbox-sweep` can import `fetchStateChangeUnread()` in a later
integration. Never route StateChange through `snappy-skool`.

## Self-correcting loader

If the live host, Circle routes, response fields, login flow, or lesson names
change, remeasure with agent-browser and Libretto before editing the contract.
Only document verbs that `api.ts` implements and the live road answers.

<!-- SKILL-INDEX-START -->
[snappy-statechange Index]|root: ~/.claude/skills/snappy-statechange|IMPORTANT: Prefer these files over pre-training assumptions for this domain. Read the relevant file when the AGENTS.md summary is insufficient.|root:{SKILL.md}
<!-- SKILL-INDEX-END -->

## Used by

Nothing in the collection names this skill.

<!-- SNAPPY-CONTRACT-VERBS-START -->
## Contract verbs

Generated from `api.ts` `HAND_CONTRACT`. Do not hand-edit this block.

| Verb | Contract arguments | Effect | First call |
|---|---|---|---|
| `health` | — | `read` | `npx tsx ~/.claude/skills/snappy-statechange/api.ts health` |
| `unread` | — | `read` | `npx tsx ~/.claude/skills/snappy-statechange/api.ts unread` |
| `posts` | — | `read` | `npx tsx ~/.claude/skills/snappy-statechange/api.ts posts` |
| `stage-post` | `title`, `body` | `write-reversible` | `npx tsx ~/.claude/skills/snappy-statechange/api.ts stage-post "<title>" "<body>"` |
| `stage-message` | `thread-url`, `body` | `write-reversible` | `npx tsx ~/.claude/skills/snappy-statechange/api.ts stage-message <thread-url> "<body>"` |

## Show the result

When an answer carries `face_hint`, show it with one `snappy_present(<answer>)` call.
See `/snappy-faces` for face selection. Human-facing images must crop to the
element, render at 2x on Retina, and fill the destination channel instead of
placing a small card in a full-page screenshot.
<!-- SNAPPY-CONTRACT-VERBS-END -->

Keyboard Shortcuts

Search in document⌘K
Focus search/
Previous file tab
Next file tab
Close overlayEsc
Show shortcuts?