Skip to content

ryanlane/felund-core

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

79 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

felund-core

Peer-to-peer group chat with gossip-based sync, optional relay for browser clients, and a terminal UI + web client.

Requirements

  • Python 3.9+ (3.11+ recommended)
  • Two terminals/devices on the same LAN or reachable network
  • Open/forwarded port (default: 9999) if connecting across networks

Setup

git clone <repo>
cd felund-core
bash setup.sh

This creates a .venv/ at the project root and installs all dependencies for both the chat client and the optional API service.

State is stored at ~/.felundchat/state.json.

Clients

Python TUI

.venv/bin/python chat/felundchat.py

Launches the panel-based terminal UI. On first run a short wizard guides you through creating or joining a circle.

β”Œβ”€ felundchat ──────────────────────────────────────────────────────┐
β”‚ node: a3f8b2 | #general | 2 peers                     ctrl+q=quit β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ Circles          β”‚ [10:32] alice: hey everyone                    β”‚
β”‚ ──────────────── β”‚ [10:33] bob: yo                                β”‚
β”‚ ● mygroup        β”‚ [10:35] you: what's up                         β”‚
β”‚   #general ←     β”‚                                                β”‚
β”‚   #random        β”‚                                                β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ > _                                                               β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

TUI keyboard shortcuts

Key Action
F3 Settings (display name, relay URL)
F2 Show invite code for active circle
F1 Help
ctrl+q Quit
Escape Re-focus input bar

TUI slash commands

Command Action
/help [command] List all commands or detail one
/invite Show invite code for the active circle
/join <code> Join a new circle via felund code
/circles List joined circles
/channels List channels in the active circle
/channel create <name> [public|key|invite] Create a channel
/channel join <name> [key] Join a channel
/channel switch <name> Switch active channel
/channel leave <name> Leave a channel
/who [channel] Show members
/name [new_name] Show or update display name
/settings Open settings modal
/debug Toggle gossip debug log
/quit Exit

Web client

A full chat client that runs in the browser. Uses the same invite codes and message format as the Python TUI β€” users on both clients can share circles. See chat-webclient/README.md for setup.

cd chat-webclient
cp .env.example .env   # set VITE_FELUND_API_BASE
npm install && npm run dev

Web client keyboard shortcuts

Key Action
F1 Help
F2 Show invite code for active circle
F3 Settings
F4 Call panel
Escape Close modals Β· focus input

Web client slash commands

Command Action
/help Show help modal
/invite Show invite code for the active circle
/join <code> Join a circle via invite code
/circles List joined circles
/circle create <name> Create a new circle
/circle name <new-name> Rename the current circle (owner only)
/circle leave Leave the active circle
/circle join <code> Alias for /join
/channels List channels in the active circle
/channel create <name> Create a new channel
/channel switch <name> Switch to another channel
/call start Start a call in the current channel
/call join Join an active call
/call leave Leave the current call
/call end End the call (host only)
/name <new_name> Change your display name
/settings Open settings modal

Relay / rendezvous server

An API server handles two concerns:

  • Rendezvous β€” peers register their endpoints; others look them up to attempt direct connections.
  • Relay β€” a simple store-and-forward message bus used by browser clients (which cannot open raw TCP connections) and useful as a fallback when direct peer connections are not possible.

PHP server (recommended for shared hosting)

Requires PHP 8.1+ with pdo_sqlite. No other dependencies.

# Development (built-in server)
php -S 0.0.0.0:8000 api/php/rendezvous.php

# Production β€” copy api/php/ into your document root.
# Apache .htaccess and an nginx config are included.

Python/FastAPI server (alternative, rendezvous-only)

Requires the api/ virtualenv.

.venv/bin/uvicorn api.rendezvous:app --reload

Note: the FastAPI server currently implements presence/rendezvous only (/v1/register, /v1/peers, /v1/health). For full relay support (/v1/messages) use the PHP server.

Connecting clients to the server

# Python TUI β€” set env var or configure via F3 in the TUI
export FELUND_API_BASE=http://your-server/api
.venv/bin/python chat/felundchat.py

# Web client β€” set in chat-webclient/.env before npm run dev / build
VITE_FELUND_API_BASE=http://your-server/api

CLI subcommands

# Initialize local node settings
.venv/bin/python chat/felundchat.py init --bind 192.168.1.10 --port 9999 --name Alice

# Create a circle + print invite code
.venv/bin/python chat/felundchat.py invite

# Join via single invite code
.venv/bin/python chat/felundchat.py join --code <felund_code>

# Start gossip service (headless)
.venv/bin/python chat/felundchat.py run

# Send a message from the command line
.venv/bin/python chat/felundchat.py send --circle-id <id> "hello world"

# Show inbox
.venv/bin/python chat/felundchat.py inbox --circle-id <id> --limit 50

# List circles or peers in a circle
.venv/bin/python chat/felundchat.py peers [--circle-id <id>]

Topology examples

LAN / same network

Both nodes on the same local network. No relay needed, no port forwarding needed. Direct TCP gossip.

Alice (192.168.1.10:9999)  ◄──────────►  Bob (192.168.1.11:9999)

Internet with port forwarding

One node has a reachable public port. The other initiates the connection. The host shares their public IP:port in the invite code.

Alice (1.2.3.4:9999, port-forwarded)  ◄──────────►  Bob (behind NAT)

Internet via relay (browser or NAT-to-NAT)

Neither peer can reach the other directly, or one is a browser client. Both push and pull messages through the relay API.

Alice (Python TUI)  ──► relay server ◄──  Bob (browser)
                              β”‚
                    (HMAC-authenticated,
                     server cannot read
                     or forge messages)

The relay is store-and-forward: messages are retained for up to 30 days. Peers pull at 5-second intervals.

Trust and threat model

  • Authentication β€” every message carries an HMAC-SHA256 MAC derived from the circle secret. Any tampered or forged message is rejected by recipients.
  • Confidentiality β€” messages are not encrypted in the current version. The relay server and any network observer can read message content. Treat felund as "tamper-evident chat," not "end-to-end encrypted chat."
  • Circle membership β€” anyone who obtains the invite code (which embeds the circle secret) can join the circle and read all messages. Protect invite codes accordingly.
  • Relay trust β€” the relay server is untrusted. It stores opaque payloads and cannot forge valid MACs without the circle secret.

Package structure

felund-core/
β”œβ”€β”€ setup.sh                  # One-shot venv + dependency install
β”œβ”€β”€ test_relay.py             # Integration test for the relay API
β”œβ”€β”€ .env.example              # Environment variable reference
β”œβ”€β”€ api/
β”‚   β”œβ”€β”€ php/
β”‚   β”‚   β”œβ”€β”€ rendezvous.php    # PHP relay + rendezvous server (recommended)
β”‚   β”‚   β”œβ”€β”€ .htaccess         # Apache rewrite rules
β”‚   β”‚   └── nginx.conf        # nginx config example
β”‚   β”œβ”€β”€ rendezvous.py         # FastAPI rendezvous server (presence only)
β”‚   └── requirements.txt
β”œβ”€β”€ chat/
β”‚   β”œβ”€β”€ felundchat.py         # Entry-point shim
β”‚   β”œβ”€β”€ requirements.txt
β”‚   └── felundchat/
β”‚       β”œβ”€β”€ config.py         # Constants (state file path, limits)
β”‚       β”œβ”€β”€ models.py         # Dataclasses: State, Circle, Peer, Channel, ChatMessage
β”‚       β”œβ”€β”€ crypto.py         # HMAC MAC generation and SHA-256 helpers
β”‚       β”œβ”€β”€ invite.py         # felund code encode/decode
β”‚       β”œβ”€β”€ transport.py      # TCP framing, IP detection
β”‚       β”œβ”€β”€ persistence.py    # load_state / save_state (JSON)
β”‚       β”œβ”€β”€ gossip.py         # GossipNode β€” TCP server + gossip loop
β”‚       β”œβ”€β”€ channel_sync.py   # Channel event messages and apply logic
β”‚       β”œβ”€β”€ rendezvous_client.py  # Relay + rendezvous API client
β”‚       β”œβ”€β”€ chat.py           # Circle/channel management helpers
β”‚       β”œβ”€β”€ cli.py            # argparse subcommands
β”‚       └── tui/              # Textual panel TUI
└── chat-webclient/           # React + TypeScript browser client

Notes

  • The app auto-detects your local IP for peer sharing.
  • Keep at least one node running so gossip can propagate messages.
  • For cross-network direct connections, ensure the chosen port is reachable from the internet.
  • Sync debug logs are local-only and off by default.

Docs

About

simple peer to peer communications network

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors