This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
IMPORTANT: before you do anything else, run the beans prime command and heed its output. Tasks for this project are tracked in .beans/ via the beans CLI.
chattolib is an async Python client library for the Chatto webchat GraphQL API (https://chat.chatto.run/api/graphql). It wraps the full Chatto GraphQL schema — queries, mutations, and subscriptions — into a typed, Pythonic async interface.
# Install in development mode
pip install -e ".[dev]"
# Run all tests
pytest
# Run a single test
pytest tests/test_foo.py::test_bar -v
# Lint & format
ruff check .
ruff format .
# Type checking
mypy src/chattolib
The library uses httpx for async HTTP and websockets for GraphQL subscriptions (real-time events via WebSocket).
src/chattolib/ChattoClient async class. Holds the httpx session, auth token, and base URL. All API methods live here or are mixed in from domain modules.| Domain | Queries | Mutations | Subscriptions |
|---|---|---|---|
| Server | server, server.profile |
updateServerConfig, uploadServerLogo, deleteServerLogo, uploadServerBanner, deleteServerBanner |
ServerUpdatedEvent, RoomGroupsUpdatedEvent |
| Rooms | room, room.events, room.event, room.eventsAround |
createRoom, updateRoom, archiveRoom, unarchiveRoom, joinRoom, leaveRoom, banRoomMember, unbanRoomMember, markRoomAsRead |
myEvents |
| Room groups | server.roomGroups |
createRoomGroup, updateRoomGroup, deleteRoomGroup, reorderRoomGroups, moveRoomToGroup, reorderRoomsInGroup, joinGroup |
RoomGroupsUpdatedEvent |
| Messages | (via room.events) | postMessage, updateMessage, deleteMessage, deleteAttachment, deleteLinkPreview |
MessagePostedEvent, MessageEditedEvent, MessageRetractedEvent |
| Assets | (via attachment IDs) | (server-driven) | AssetProcessingStartedEvent, AssetProcessingSucceededEvent, AssetProcessingFailedEvent, AssetDeletedEvent |
| Reactions | (on message events) | addReaction, removeReaction |
ReactionAddedEvent, ReactionRemovedEvent |
| Threads | room.event.threadReplies (via MessagePostedEvent), viewer.followedThreads |
followThread, unfollowThread, markThreadAsRead |
ThreadCreatedEvent, ThreadFollowChangedEvent |
| Users | viewer.user, user(id), userByLogin, server.members |
updateProfile, uploadAvatar, deleteAvatar, updateSettings, requestAccountDeletion, deleteMyAccount |
UserCreatedEvent, UserDeletedEvent, UserProfileUpdatedEvent, PresenceChangedEvent |
| DMs | (via rooms) | startDM |
NewDirectMessageNotificationEvent |
| Notifications | viewer.notifications (connection), viewer.hasNotifications |
dismissNotification, dismissAllNotifications, setServerNotificationLevel, setRoomNotificationLevel |
NotificationCreatedEvent, NotificationDismissedEvent, NotificationLevelChangedEvent, MentionStatusClearedEvent |
| Push | — | subscribeToPush, unsubscribeFromPush |
— |
| Permissions/Roles | admin.rbac, server.roles |
grantPermission, revokePermission, createRole, updateRole, deleteRole, assignRole, plus room/user/group variants |
— |
| Voice calls | room.voiceCallToken, activeCallRoomIds, room.callParticipants |
— | CallParticipantJoinedEvent, CallParticipantLeftEvent |
| Admin | admin.systemInfo, admin.serverConfig, admin.eventLog, admin.roomBans, admin.projections |
admin.updateUser, admin.updateBlockedUsernames, admin.clearUsernameCooldown |
via myEvents |
ID scalar).Int64 scalar (e.g., byte counts) — map to Python int.Upload scalar (multipart form).limit/before/after on room events (before/after are Time scalars, ISO timestamps).input argument with a corresponding *Input type.myEvents for all server, room, and instance events.type field: CHANNEL or DM. Channels live inside a RoomGroup (groupId is required at creation).threadRootEventId (no separate inThread field on messages).PresenceStatus (OFFLINE/ONLINE/AWAY/DO_NOT_DISTURB) is the observable type; PresenceStatusInput (no OFFLINE) is what callers can set via updateMyPresence.width, height, fit (enum: CONTAIN, COVER, EXACT) for server-side resizing.snake_case (translated from GraphQL camelCase)PascalCase matching the GraphQL type namesverb_noun style (e.g., create_room, post_message, mark_room_as_read)