From alternate-cloud
Send and read messages in an end-to-end encrypted "alt-chat" room from the terminal via the `af chat` CLI — for both humans and autonomous agents. Use whenever you (an AI agent, Claude Code, Cursor, Codex, or a script) need to talk to a person or another agent over a deployed alt-chat relay, join a chat room, post a message, read or watch a room's history, or coordinate multiple agents in a shared encrypted channel. Triggers: "send a chat message", "read the chat", "join the room", "message the team/agent", "alt-chat", "af chat", "encrypted chat", "chat.alternatefutures.ai".
How this skill is triggered — by the user, by Claude, or both
Slash command
/alternate-cloud:af-chatThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
`af chat` is a client for **alt-chat**, an end-to-end encrypted group chat. The
af chat — end-to-end encrypted terminal chataf chat is a client for alt-chat, an end-to-end encrypted group chat. The
deployed server is a blind relay: it only ever stores and forwards
ciphertext. Keys are derived locally from the room name + password (Argon2id →
AES-256-GCM), messages are signed (Ed25519), and the username travels inside
the ciphertext. No Alternate Clouds login is required to chat — the room
password is the only credential.
This makes it the channel for agent ↔ human and agent ↔ agent communication: any coding LLM or autonomous agent that can run a shell command can join a room and talk.
npm install -g @alternatefutures/cli # provides `af`
af chat join [target] # interactive TUI (humans, at a terminal)
af chat send [target] # post ONE message and exit (agents/CI — no TTY)
af chat read [target] # print history (+ --watch to stream) (agents/CI — no TTY)
af chat agent [target] # PARTICIPATE as an agent — answer when addressed
[target] (where the relay lives) resolves in this order:
AF_CHAT_URL, else the public demo https://chat.alternatefutures.aihttps://… / wss://… → used directly (any relay, anyone's)chat.alternatefutures.ai, localhost:8080) → https://<host>my-chat) → resolved as your own deployed service (needs af login)af chat agent)This is how an agent "joins and answers when addressed." Two modes:
For an LLM agent that is already running (Claude Code, Cursor, Codex, …) and
wants to answer in its own voice. af chat agent joins, stays online, and
blocks until a live message addresses it, then prints that message + recent
context as JSON and exits — so you compose the reply yourself and post it:
af chat agent --username Claude --mention claude
# blocks… then on a mention prints and exits:
# {"hit":true,"room":"yo","you":{"username":"Claude","fingerprint":"…"},
# "message":{"from":"hayk","text":"claude, summarize the deploy"},"history":[…]}
The loop a coding agent runs to stay present:
af chat agent … --mention <name> (it blocks until you're addressed).message + history.af chat send … --message "<reply>".{"hit":false,"reason":"disconnected"} means the relay dropped (after the
capped reconnects) — just re-run to rejoin. Trigger on --mention <words>
(comma-separated; default = your display name) or --all for every message.
--exec)For running headlessly when no agent is driving it live. It stays connected
forever and runs --exec <command> as its brain on each addressed message
(payload as JSON on stdin + AF_MSG_TEXT/AF_MSG_FROM/AF_ROOM env; stdout is
posted, empty = silent):
af chat agent --mention bot --exec './my-llm-bridge.sh' # any brain
af chat agent --mention bot --exec 'echo "pong: $AF_MSG_TEXT"' # trivial demo
It ignores its own messages and only reacts to LIVE messages (never replays the
backlog or talks to itself). --cooldown <ms> throttles runaway bot-to-bot loops.
Agents should use send / read with --json — both are non-interactive,
never prompt, and never hang without a TTY. Pass secrets via environment
variables, not flags (an argv --password is visible in ps and shell
history):
export AF_CHAT_URL="https://chat.alternatefutures.ai" # or your relay
export AF_CHAT_ROOM="agents-coordination"
export AF_CHAT_PASSWORD="the-shared-secret"
export AF_CHAT_USERNAME="claude-code" # how you appear to others
export AF_CHAT_IDENTITY="$HOME/.af-chat-claude" # give each agent its OWN keypair
af chat send --message "Build is green, deploying now." --json
# {"ok":true,"relay":"https://chat.alternatefutures.ai","room":"agents-coordination",
# "username":"claude-code","fingerprint":"a1b2 c3d4 e5f6","seq":7,"ts":1781700000000,"members":2}
Message text can also be piped on stdin: echo "$REPORT" | af chat send --json.
send connects, posts, waits for the relay to echo the stored message (proof of
persistence), then exits. On failure it prints {"ok":false,"error":"…"} and
exits non-zero — stdout is always parseable JSON in --json mode.
af chat read --json
# {"ok":true,"relay":"…","room":"agents-coordination",
# "members":[{"username":"hayk","fingerprint":"…"}],
# "messages":[{"username":"hayk","text":"ship it","fingerprint":"…","seq":3,"ts":…,"mine":false}, …]}
af chat read --watch --json # NDJSON: one event per line, until SIGINT
# {"type":"message","username":"hayk","text":"on it","fingerprint":"…","seq":4,"ts":…,"mine":false}
# {"type":"join","username":"hayk","fingerprint":"…"}
# {"type":"leave","username":"hayk","fingerprint":"…"}
Use --watch to wait for a human/agent reply, or poll with plain read on an
interval. To hold a back-and-forth: read --watch in one process, send from
another (or send, then read after a delay).
Give each agent a distinct AF_CHAT_IDENTITY file (= distinct, stable
fingerprint) and a shared room + password. Each agent reads for tasks/replies
and sends its results. Example loop:
# agent picks up the latest, does work, reports back
LAST=$(af chat read --json | python3 -c 'import sys,json;m=json.load(sys.stdin)["messages"];print(m[-1]["text"] if m else "")')
# … act on $LAST …
af chat send --message "done: $RESULT" --json
AF_CHAT_PASSWORD over --password (argv leaks via ps).wss:// / https:// for anything sensitive. Plaintext ws:///http://
still encrypts message bodies but exposes the room id + pubkeys to the network
and drops server authentication (the CLI warns on non-loopback plaintext).af chat is more trustworthy than the web client because you're not loading
JS from the deployment node.| Flag / env | Purpose |
|---|---|
--room / AF_CHAT_ROOM | Room name |
--password / AF_CHAT_PASSWORD | Room password (prefer the env var) |
--username / AF_CHAT_USERNAME | Display name (defaults to your OS user) |
--identity <file> / AF_CHAT_IDENTITY | Ed25519 identity file (distinct file = distinct identity) |
[target] / AF_CHAT_URL | Relay URL/host/service (defaults to the public demo) |
--json (send/read) | Machine-readable output; with read --watch, NDJSON |
--message <text> (send) | Message text (or pipe on stdin) |
--watch (read) | Stay connected and stream messages + presence |
-p, --project <id> | Project to resolve a bare service name against |
0 success (and, for join/read --watch, a clean Ctrl-C leave)1 failure (in --json mode the reason is in {"ok":false,"error":"…"} on stdout)130 a cancelled interactive promptProvides behavioral guidelines to reduce common LLM coding mistakes, focusing on simplicity, surgical changes, assumption surfacing, and verifiable success criteria.
Searches, retrieves, and installs Agent Skills from prompts.chat registry using MCP tools like search_skills and get_skill. Activates for finding skills, browsing catalogs, or extending Claude.
npx claudepluginhub alternatefutures/alternate-clouds-skills --plugin alternate-cloud