Skip to main content

Wasat: Async Gemini Protocol Client Library

Wasat is a fully type-hinted asynchronous client library for the Gemini Protocol, relying only on cryptography for certificate management.

Features

  • Async All the Way: Built on top of Python's standard asyncio loop with streaming/chunking support.
  • Type Safe: Fully typed API.
  • TOFU & Hybrid Verification: Supports CA, TOFU, and Hybrid (CA validation with TOFU fallback) verification modes with built-in file-based trust stores and interactive hooks.
  • Auto Redirect Handling: Automatically handles temporary and permanent redirects (with protection against loops and infinite redirect limits), caching permanent redirects locally.
  • Client Authentication: Native support for client TLS certificates.
  • Minimal Dependencies: Relies only on cryptography for certificate management, otherwise using Python's standard library.
  • CLI Utility: Includes a wasat command-line interface out of the box.

Installation

wasat is available from pypi and can be installed with your package installer of choice.

With pip:

pip install wasat

With uv:

uv add wasat

Quick Start

1. Make a Simple Request

Use Client with standard async context managers to query a Gemini capsule and decode the response:

import asyncio
from wasat import Client, WasatError

async def main():
    # 'tofu' mode is ideal for standard Gemini capsules (self-signed certs)
    client = Client(verify_mode="tofu")

    try:
        # Perform the request (automatically resolves host, port, TLS, and redirects)
        async with await client.request("gemini://geminiprotocol.net/") as response:
            print(f"Status: {response.status.value} ({response.status.name})")
            print(f"MIME type: {response.mime_type}")

            # Fetch the decoded body text
            body = await response.text()
            print(body)

    except WasatError as error:
        print(f"Request failed: {error}")

if __name__ == "__main__":
    asyncio.run(main())

2. Streaming Chunk Responses

For large files or media streams, read the response body in chunks to prevent exhausting memory:

async with await client.request("gemini://example.com/large-file.txt") as response:
    if response.status.is_success:
        async for chunk in response.iter_chunks(chunk_size=1024):
            # Process each chunk as it arrives
            sys.stdout.buffer.write(chunk)

3. Client Certificate Authentication

If a server requires client auth (status code 60), supply your certificate files to the client configuration:

client = Client(
    verify_mode="tofu",
    client_cert="/path/to/client.crt",
    client_key="/path/to/client.key"  # Optional if key is embedded in cert
)

4. Interactive TOFU Confirmation

Implement a custom asynchronous callback to prompt the user before trusting new self-signed certificates:

import sys

async def confirm_cert(host: str, port: int, fingerprint: str) -> bool:
    print(f"New certificate encountered for {host}:{port}")
    print(f"Fingerprint: sha256:{fingerprint}")
    response = input("Do you trust this certificate? [y/N]: ").strip().lower()
    return response == "y"

client = Client(
    verify_mode="tofu",
    on_new_certificate=confirm_cert
)

Command Line Interface (CLI)

Wasat comes with a command-line interface to fetch Gemini capsules from your shell:

# Basic fetch using the entrypoint script (uses TOFU)
uv run wasat gemini://geminiprotocol.net/

# Alternatively, execute the package directly using python -m
uv run python -m wasat gemini://geminiprotocol.net/

# Fetch a local or custom port capsule
uv run wasat gemini://localhost:1965/index.gmi

License

MIT

Release files for wasat 1.6.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 wasat 1.6.0
File Size Uploaded
wasat-1.6.0.tar.gz 33.3 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for wasat 1.6.0
File Interpreter ABI Platform
wasat-1.6.0-py3-none-any.whl Python 3 none any Details

Total release size: 70.3 kB

Release files / wasat-1.6.0.tar.gz

Download URL wasat-1.6.0.tar.gz
Size 33.3 kB
Tags Source
SHA-256 checksum
How to use checksums
9c41312bd46cfa8f072beda060f330f0940265828e86086d4363f13575dced7b
BLAKE2b-256 checksum
How to use checksums
9d73709c55daf3aae901becb8faa335dcbe02a3aefe43960999ca97a2f6f0041
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.12.6 {"installer":{"name":"uv","version":"0.12.6","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

Release files / wasat-1.6.0-py3-none-any.whl

Download URL wasat-1.6.0-py3-none-any.whl
Size 37.0 kB
Tags Python 3
SHA-256 checksum
How to use checksums
8b0d9c3a3bbed05b39b6cc682b223881380174b95d0f2df8554341ff011183ef
BLAKE2b-256 checksum
How to use checksums
d16f6092640dd43edd79a274860ef167865355cab9d335fe6c8439175728794e
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.12.6 {"installer":{"name":"uv","version":"0.12.6","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

Release history Release notifications | RSS feed

1.9.1

2 release files

1.9.0

2 release files

1.8.1

2 release files

1.8.0

2 release files

1.7.0

2 release files

This release

1.6.0 This release

2 release files

1.5.0

2 release files

1.4.0

2 release files

1.3.1

2 release files

1.3.0

2 release files

1.2.0

2 release files

1.0.1

2 release files

1.0.0

2 release files

0.8.0

2 release files

0.7.0

2 release files

0.6.1

2 release files

0.6.0

2 release files

0.5.0

2 release files

0.4.0

2 release files

0.3.2

2 release files

0.3.1

2 release files

0.3.0

2 release files

0.2.1

2 release files

0.2.0

2 release files

0.1.0

2 release files

0.0.1

2 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