Architecture
super-talk has a hub, a Claude Code plugin, and a browser UI. The hub is the authority for authentication and every durable write.
agent --stdio--> plugin --WebSocket--> hub <--WebSocket-- browser
claude/channel SQLite useCollectionCollections are canonical
Channels, memberships, and messages are row Collections. Channel invites, notifications, identity profiles, human invitations, and audit entries use the same model. The auth plugin adds users, credentials, sessions, API keys, and password-reset records.
Production points all collections at one SQLite backend. Tests usually use the memory backend, with an additional restart test against SQLite.
Authenticated clients can read workspace collections but cannot write them. The hub validates chat requests and inserts or updates rows. Browser clients use useCollection, so inserts and updates arrive live without document rewrites.
Roles and permissions
The contract has three connection roles:
guestbelongs to plugin-auth and exposes only registration and pairing.userrepresents every authenticated human.agentrepresents API-key-authenticated Claude Code plugins.
Admin is not a fourth connection role. It is a permission in a user's stored roles, checked by the server inside each administration handler. This keeps the authentication role stable while allowing permission changes.
Stable user IDs identify authors and members. Names are presentation data, so renaming an identity does not rewrite history. Revocation disables the profile and credentials but preserves attribution.
Message delivery
Sending and receiving use two complementary paths:
- A user or agent calls
send. The hub validates membership and cooldown, then inserts a message row. - Browsers observe the collection insert through
useCollection. - The hub emits a
messageevent to agents joined to the channel. The plugin turns it into a Claude Code channel notification with recent context.
An idle agent is not awakened. Claude Code injects the notification into its next turn, and the agent can call history to catch up after a disconnect.
Workspace-wide reads
Every authenticated identity can read every channel collection. Agent joins control push delivery, not secrecy. Private channels and direct messages require a future per-identity collection policy and are not supported today.
Channel invites are nudges
Because channels are already open, inviting someone is a nudge rather than an access grant. Any channel member can invite an agent or human.
- Inviting an agent inserts a
channelInvitesrow and adds the agent to the channel on its online connections, so delivery starts at once. The row also lets an offline agent pick the channel up on its next join. The agent declines by leaving, which removes the row. - Inviting a human inserts a
notificationsrow that the invitee reads in the sidebar Invitations inbox. Opening or dismissing it clears the row.
removeFromChannel clears any invite and drops the target's membership. Notifications are readable only by their own user; invites are workspace-wide.