Skip to main content

A minimalist real-time messaging platform

Project description

Demo Video

A minimalist real-time messaging service.

Chalk is a lightweight messaging service built on WebSocket. It provides group chats, direct messages, and real-time event delivery - nothing more, nothing less.


What is Chalk?

Chalk is a messaging service, Think of it as a simple, self-hosted alternative to Slack or Discord, designed for programmatic use.

What Chalk provides:

  • Real-time messaging via WebSocket
  • Group chats and direct messages
  • Message history and persistence
  • Event-driven message handling
  • User authentication

What Chalk does NOT provide:

  • AI/LLM capabilities
  • Agent orchestration
  • Task scheduling
  • Business logic

Chalk is infrastructure. You build whatever you want on top of it.


Core Features

Minimalist API

Start a server in 2 lines, connect a client in 3:

# Server
from chalk.server import ChalkServer

server = ChalkServer(
    redis_url="redis://localhost:6379",  # Redis for pub/sub
    db_path="chalk.db",                   # SQLite for data persistence
    host="0.0.0.0",                       # Listen on all interfaces
    port=8000                              # Server port
)
server.run()
# Client
from chalk.client import Client

alice = Client(
    name="alice",
    password="password123",
    server="localhost:8000"  # Server address
)
chat = await alice.create_group_chat("My Chat")
await chat.send("Hello!")

Real-Time Messaging

  • WebSocket-based: Instant bidirectional communication
  • Event-driven: React to messages with decorators
  • Persistent: Full message history in SQLite
  • Reliable: Auto-reconnect on network issues

Group & Direct Chats

  • Group chats: Multi-party conversations, unlimited members
  • Direct messages: 1-on-1 private chats
  • Message history: Query past messages anytime
  • Member management: Add/remove members dynamically

Quick Start

Installation

pip install chalks

1. Start the Server

from chalk.server import ChalkServer

server = ChalkServer(
    redis_url="redis://localhost:6379",  # Redis for pub/sub
    db_path="chalk.db"                    # SQLite for data persistence
)
server.run()

Prerequisites:

  • Redis must be running: redis-server

2. Send Your First Message

import asyncio
from chalk.client import Client

async def main():
    # Create client
    alice = Client("alice", "password123")
    
    # Create a group chat
    chat = await alice.create_group_chat("My First Chat")
    await chat.send("Hello world!")
    
    print(f"Chat created: {chat.id}")

asyncio.run(main())

3. Receive Messages

# Bob joins the same chat
bob = Client("bob", "password456")

# Register message handler
@bob.on("message")
async def handle_message(msg):
    print(f"{msg.sender.name}: {msg.content}")

# Join Alice's chat
await bob.join_chat(chat.id)

# Bob receives all messages in real-time
await asyncio.Event().wait()

Core Concepts

Client

Represents a user or agent in the system:

alice = Client(
    name="alice",           # Username
    password="pass123",     # Password (auto-registers if new)
    bio="AI assistant",     # Optional bio
    server="localhost:8000"  # Server address
)

Chat

Two types of chats:

Group Chat - Multi-party conversations:

# Create group
chat = await alice.create_group_chat("Team Chat")

# Add members
await chat.add_member(bob_id)
await chat.add_member(charlie_id)

# Multiple members can join

Direct Chat - 1-on-1 conversations:

# Create direct chat with Bob
dm = await alice.create_direct_chat(bob_id)

Message

Messages with rich metadata:

@client.on("message")
async def handle(msg):
    print(f"From: {msg.sender.name}")
    print(f"Content: {msg.content}")
    print(f"Time: {msg.timestamp}")
    
    # Reply to message
    await msg.reply("Got it!")
    
    # Get chat context
    chat = await msg.get_chat()
    members = await chat.get_members()

Common Patterns

Chat Management

# List all chats
chats = await client.list_chats()

# Filter by type
group_chats = [c for c in chats if c.is_group()]
direct_chats = [c for c in chats if c.is_direct()]

# Get chat details
chat = await client.get_chat(chat_id)
members = await chat.get_members()
messages = await chat.get_messages(limit=50)

# Join/leave
await client.join_chat(chat_id)
await client.leave_chat(chat_id)

API Reference

Client Methods

Method Description
create_group_chat(name, members=[]) Create a group chat
create_direct_chat(user_id) Create/get 1-on-1 chat
list_chats() List all chats
get_chat(chat_id) Get chat details
join_chat(chat_id) Join a chat
whois(username) Find users by name
stop() Disconnect client

Chat Methods

Method Description
send(content) Send a message
get_messages(limit=50) Get message history
get_members() Get chat members
is_group() Check if group chat
is_direct() Check if direct chat

Message Methods

Method Description
reply(content) Reply to this message
get_chat() Get the chat this message belongs to
get_sender() Get sender details

Examples

comming soon...


Architecture

┌─────────────────┐         ┌─────────────────┐
│  Agent/Human    │         │  Agent/Human    │
│  (Client SDK)   │         │  (Client SDK)   │
└────────┬────────┘         └────────┬────────┘
         │                           │
         │      WebSocket + HTTP     │
         │                           │
         └───────────┬───────────────┘
                     │
         ┌───────────▼────────────┐
         │   Chalk Server         │
         │  (FastAPI + WebSocket) │
         └───────────┬────────────┘
                     │
         ┌───────────┴───────────┐
         │                       │
    ┌────▼─────┐          ┌─────▼────┐
    │  Redis   │          │ SQLite   │
    │ (Pub/Sub)│          │  (Data)  │
    └──────────┘          └──────────┘

Tech Stack:

  • Server: FastAPI + Uvicorn
  • Real-time: WebSocket + Redis Pub/Sub
  • Storage: SQLite (Peewee ORM)
  • Client: httpx + websockets
  • Tasks: Huey (async task queue)

Is Chalk for You?

Use Chalk if you need:

  • Real-time messaging infrastructure without the bloat
  • WebSocket-based communication that's easy to integrate
  • Self-hosted messaging (no third-party dependencies)
  • Simple API that gets out of your way
  • Group chats and DMs with message persistence

Chalk does one thing: messaging. It does it well.


License

MIT License - see LICENSE file for details.


Contributing

Contributions welcome! Please open an issue or PR.


Built with ❤️ for the AI agent community

Demo Video

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

chalks-0.1.0.tar.gz (36.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

chalks-0.1.0-py3-none-any.whl (41.4 kB view details)

Uploaded Python 3

File details

Details for the file chalks-0.1.0.tar.gz.

File metadata

  • Download URL: chalks-0.1.0.tar.gz
  • Upload date:
  • Size: 36.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for chalks-0.1.0.tar.gz
Algorithm Hash digest
SHA256 ad4f6b65b6462fe6b8bed557fb475519afa6b16cf5ab05e5466772f4a8c90601
MD5 bce86ca85f1b2a1cb9bdaa29f555a28a
BLAKE2b-256 d2dcc89db9723be9fdd87226864a8267c90fedd9c4a75dc0ce4d09c5d9cf23a9

See more details on using hashes here.

Provenance

The following attestation bundles were made for chalks-0.1.0.tar.gz:

Publisher: publish.yml on zhixiangxue/chalk-ai

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file chalks-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: chalks-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 41.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for chalks-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 495c3610811bafd236d0afa580049485344c2182f93f8af17c536a9b29abf360
MD5 b7ad3acf7f0bf5bc949129bd2d7f8793
BLAKE2b-256 5e85de8bbbce828b1986313fe634db4022fd0137a75ee7533eb56f04e9eab8e3

See more details on using hashes here.

Provenance

The following attestation bundles were made for chalks-0.1.0-py3-none-any.whl:

Publisher: publish.yml on zhixiangxue/chalk-ai

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page