Skip to main content

ReplyFast

Signal messaging library for Python using Presage (Rust).

Installation

uv pip install replyfast

# With optional dependencies
uv pip install replyfast[scheduler]  # For cron scheduling
uv pip install replyfast[qrcode]     # For QR code display
uv pip install replyfast[all]        # Everything

Contents

Quick Start

from replyfast import SignalClient

# Create client
client = SignalClient("./data")

# Link as secondary device (first time only)
def on_url(url):
    print(f"Scan this QR code with Signal app: {url}")

client.link_device_sync("MyDevice", on_url)

# Send a message
client.send_message_sync("recipient-uuid", "Hello!")

# Or find contact by phone/name first
contact = client.find_contact_by_phone_sync("+1234567890")
if contact:
    client.send_message_sync(contact.uuid, "Hello!")

# Receive messages
def on_message(msg):
    if msg.is_queue_empty:
        print("Initial sync complete")
        return True

    print(f"From: {msg.sender}, Body: {msg.body}")
    return True  # Return True to continue, False to stop

client.receive_messages_sync(on_message)

API Reference

SignalClient

Method Description
is_registered_sync() Check if device is linked
link_device_sync(name, callback) Link as secondary device
send_message_sync(uuid, message) Send message to contact
send_group_message_sync(group_id, message) Send message to group
receive_messages_sync(callback) Receive messages with callback
get_contacts_sync() List synced contacts
get_groups_sync() List groups
find_contact_by_phone_sync(phone) Find contact by phone number
find_contacts_by_name_sync(name) Find contacts by name
whoami_sync() Get account info

Message

Field Type Description
sender str Sender's UUID
body str | None Message text
timestamp int Unix timestamp (ms)
group_id str | None Group ID if group message
is_read_receipt bool Is read receipt
is_typing_indicator bool Is typing indicator
is_queue_empty bool Initial sync complete marker

Signal Handling

The library handles SIGINT (Ctrl+C) cleanly. When you press Ctrl+C during receive_messages_sync(), it will:

  1. Stop the receive loop gracefully
  2. Raise KeyboardInterrupt in Python
  3. Allow cleanup code to run
try:
    client.receive_messages_sync(on_message)
except KeyboardInterrupt:
    pass  # Clean exit

print("Stopped")

Scheduler

Send messages at scheduled times using cron syntax.

Scheduler with Message Receiving

When running a bot that both receives messages and runs scheduled tasks, start the scheduler after the initial sync is complete (indicated by is_queue_empty):

import time
from replyfast import SignalClient, Scheduler

client = SignalClient("./data")
scheduler = Scheduler()

# Define scheduled task
def periodic_task():
    client.send_message_sync("recipient-uuid", "Scheduled message!")

# Register jobs before starting
scheduler.register(
    "*/5 * * * *",  # Every 5 minutes
    periodic_task,
    name="periodic-task"
)

# Message handler that starts scheduler after sync
def on_message(msg):
    # Start scheduler once initial sync is complete
    if msg.is_queue_empty:
        print("Ready to receive messages")
        scheduler.start()  # Start scheduler in background
        return True

    if msg.body:
        print(f"From: {msg.sender}: {msg.body}")
        # Handle commands here

    return True

# Run with reconnection loop for long-running bots
reconnect_delay = 5

while True:
    try:
        client.receive_messages_sync(on_message)
        break  # Normal exit
    except KeyboardInterrupt:
        break  # Ctrl+C
    except Exception as e:
        print(f"Connection error: {e}")
        print(f"Reconnecting in {reconnect_delay}s...")
        time.sleep(reconnect_delay)
        reconnect_delay = min(reconnect_delay * 2, 300)  # Max 5 min

scheduler.stop()
print("Stopped")

Scheduler Only (No Message Receiving)

from replyfast import SignalClient, Scheduler

client = SignalClient("./data")
scheduler = Scheduler()

def send_greeting():
    contact = client.find_contact_by_phone_sync("+1234567890")
    if contact:
        client.send_message_sync(contact.uuid, "Good morning!")

scheduler.register(
    "0 9 * * *",  # cron: minute hour day month weekday
    send_greeting,
    name="morning-greeting"
)

# Run scheduler (blocking)
scheduler.run()

# Or run in background
scheduler.start()
# ... do other things ...
scheduler.stop()

Cron Expression Format

┌───────────── minute (0-59)
│ ┌───────────── hour (0-23)
│ │ ┌───────────── day of month (1-31)
│ │ │ ┌───────────── month (1-12)
│ │ │ │ ┌───────────── day of week (0-6, 0=Sunday)
│ │ │ │ │
* * * * *

Examples:

  • */5 * * * * - Every 5 minutes
  • 0 9 * * * - Every day at 9:00 AM
  • 0 9 * * 1-5 - Weekdays at 9:00 AM
  • 30 */2 * * * - Every 2 hours at minute 30

Decorator Syntax

from replyfast import schedule, get_scheduler

@schedule("0 9 * * *")
def daily_task():
    print("Runs every day at 9 AM")

get_scheduler().start()

Examples

The examples/ directory contains complete working examples:

example.py

Basic usage showing how to list contacts, groups, and receive messages with proper signal handling:

python examples/example.py

Demonstrates:

  • Checking registration status
  • Getting account info with whoami_sync()
  • Listing contacts and groups
  • Receiving messages with callback
  • Handling typing indicators and read receipts
  • Clean Ctrl+C shutdown

demo_bot.py

A bot that sends system stats on a schedule while also responding to commands:

DEMO_RECIPIENT=<uuid> python examples/demo_bot.py

Demonstrates:

  • Scheduler with message receiving (starts after is_queue_empty)
  • Multiple scheduled jobs (df -h every 5 min, free -m every hour)
  • Interactive commands (ping, df, free, help)
  • Reconnection loop with exponential backoff
  • Proper cleanup on shutdown

Requirements

  • Python 3.10+
  • Rust toolchain (for building from source)

License

AGPL-3.0-or-later

Release files for replyfast 0.4.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for replyfast 0.4.0
File Size Uploaded
replyfast-0.4.0.tar.gz 70.2 kB Details

Built distributions (wheels)

Table of built distributions (wheels) for replyfast 0.4.0
File
replyfast-0.4.0-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl CPython 3.10 abi3 Linux glibc 2.17+ x86-64 Details
replyfast-0.4.0-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl CPython 3.10 abi3 Linux glibc 2.17+ ARM64 Details
replyfast-0.4.0-cp310-abi3-macosx_11_0_arm64.whl CPython 3.10 abi3 macOS 11.0+ ARM64 Details
replyfast-0.4.0-cp310-abi3-macosx_10_12_x86_64.whl CPython 3.10 abi3 macOS 10.12+ x86-64 Details

Total release size: 38.7 MB

Release files / replyfast-0.4.0.tar.gz

Download URL replyfast-0.4.0.tar.gz
Size 70.2 kB
Tags Source
SHA-256 checksum
How to use checksums
276e6bfdbda9cf3baae39c02150b1f4150bde30c023cd8b3d7012acaf3fb9f82
BLAKE2b-256 checksum
How to use checksums
8b3cc796b74095fb50b94dab998eebe97a7635a78ac0c19e45ecc9027b1c499c
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 14, 2026.

Transparency log

Release files / replyfast-0.4.0-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl

Download URL replyfast-0.4.0-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Size 9.9 MB
Tags CPython 3.10 Linux glibc 2.17+ x86-64 abi3
SHA-256 checksum
How to use checksums
624ebcbfb1e45939f9aef0adf50d2f49004bd1e0ce8d3d6213db4b80c0481064
BLAKE2b-256 checksum
How to use checksums
b18db46e86026a3d65230e9d97c3d0e5254c487404962786fca38b05c29c57ba
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 14, 2026.

Transparency log

Release files / replyfast-0.4.0-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl

Download URL replyfast-0.4.0-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Size 10.5 MB
Tags CPython 3.10 Linux glibc 2.17+ ARM64 abi3
SHA-256 checksum
How to use checksums
1bb9fc0b0632db568c2785cbddf93626c2cc1e5efb802af0d00c683b0cb32e9c
BLAKE2b-256 checksum
How to use checksums
2e4c278b44e51ca6add39a3f383431bbde07c7d9dfe765328a42a7e0f746e561
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 14, 2026.

Transparency log

Release files / replyfast-0.4.0-cp310-abi3-macosx_11_0_arm64.whl

Download URL replyfast-0.4.0-cp310-abi3-macosx_11_0_arm64.whl
Size 9.1 MB
Tags CPython 3.10 abi3 macOS 11.0+ ARM64
SHA-256 checksum
How to use checksums
16b4049c5321e6b362e557a3a26af854bbaa4928ede1c15b215807131c8729a4
BLAKE2b-256 checksum
How to use checksums
8a7dc1d133ba40d77f950277c48ced160b56b25b64de716415c157d9bde1695f
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 14, 2026.

Transparency log

Release files / replyfast-0.4.0-cp310-abi3-macosx_10_12_x86_64.whl

Download URL replyfast-0.4.0-cp310-abi3-macosx_10_12_x86_64.whl
Size 9.1 MB
Tags CPython 3.10 abi3 macOS 10.12+ x86-64
SHA-256 checksum
How to use checksums
4da3883663729a072425c784b65f11e44ecbae33e19b0f2c3d7ba92f27412a46
BLAKE2b-256 checksum
How to use checksums
e83aabb1ddbd6f55713a6be15d51badbee16f61c5e3203f433658a02aab7500d
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 14, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.4.0 This release

5 release files

0.3.0

5 release files

0.1.0

5 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page