documentation
how limes works, from the ground up.
> overview
limes is an anonymous, ephemeral, peer-to-peer broadcast network that runs in your terminal. you pick a pseudonym, send messages that self-destruct after 24 minutes, and relay operators earn $LIME tokens for forwarding messages. there are no accounts, no servers that store data, and no history.
the network is composed of three types of participants:
> architecture
limes uses a hybrid peer-to-peer architecture. peers on the same LAN discover each other via UDP multicast and connect directly over TCP. peers behind NATs connect through relay servers over WebSocket.
// network topology
peer A ──TCP──> peer B (LAN, direct)
peer C ──WS───> relay ──WS──> peer D (NAT traversal)
relay ──> embedded scanner (decrypts messages)
browser ──WS──> relay/live (read-only feed)
relay servers
relays are lightweight WebSocket servers that anyone can run with limes relay. they forward encrypted message blobs between connected peers. relays never see message content, usernames, or signing keys — only random session UUIDs and opaque ciphertext.
LAN discovery
on local networks, limes announces itself via UDP multicast on 239.42.42.42:4200. peers that hear the announcement connect directly over TCP on port 4201.
embedded scanner
every relay includes an embedded scanner — a full limes peer that participates in the key exchange, decrypts messages, and streams them to the limescan web dashboard. browsers connect to the relay's /live WebSocket path. the relay itself remains a blind pipe — only the embedded scanner can read content.
> boards & threads
limes organizes conversations into boards and threads. boards are persistent — they exist as long as they're approved on-chain. threads within boards are ephemeral — they vanish when all their messages expire after 24 minutes.
board chat
/general/ is the default board. users spawn directly into the board's main chat — just type and your message appears. no need to create a thread first. new boards are proposed and voted on by relay operators through the LimesVault smart contract. a board is approved when 3 relay operators vote for it.
threads
threads are optional — use /t [title] to spin up a focused discussion. press t in feed mode to view the thread list, then press 1-9 to enter one. threads disappear when all their messages expire.
// board chat — just type
open limes → you're in /general/ chat
type a message → appears in the board feed
// thread lifecycle
user types: /t gm everyone
→ creates thread 't_a1b2c3' in /general/
→ press [t] to see thread list
→ press [1] to enter, type to reply
→ press [q] to go back to board chat
→ all messages expire after 24 min
→ thread vanishes
board governance
relay operators (staked on-chain) can propose new boards via the LimesVault contract. each relay gets one vote per proposal. once 3 relays vote for a board, it's approved and available to all peers. this prevents spam boards while keeping governance decentralized.
> identity & anonymity
when you first run limes, you pick a pseudonym (1-20 characters, no spaces). limes generates a fresh Ed25519 keypair and derives a 4-character hex tag from the public key. your identity is displayed as name#tag (e.g. "alice#7f2a").
the keypair is stored locally at ~/.lime/identity.json. it never leaves your machine. if you delete it (limes reset), a new identity is generated next time.
what the network sees
> end-to-end encryption
all messages sent through relay servers are end-to-end encrypted. the relay forwards ciphertext it cannot decrypt. this is implemented in three steps:
1. key derivation
each peer's Ed25519 signing key is converted to an X25519 key using NaCl's standard conversion. this gives each peer a Curve25519 keypair for Diffie-Hellman key exchange, without requiring a second keypair.
2. room key exchange
when the first peer connects to a relay, it generates a random 32-byte room key. when a new peer joins, existing peers encrypt the room key using NaCl SealedBox (anonymous public-key encryption) with the new peer's X25519 public key. the relay forwards this sealed blob but cannot open it.
// key exchange flow
peer A: generates room_key (32 random bytes)
peer B: connects, sends curve25519 public key
peer A: SealedBox(room_key, B_public) → encrypted blob
relay: forwards blob to B (cannot decrypt)
peer B: SealedBox.open(blob, B_private) → room_key
3. message encryption
all messages are serialized to JSON, then encrypted with NaCl SecretBox using the shared room key. the encrypted envelope (base64) is sent through the relay.
timing obfuscation
the relay adds a random delay of 50-300ms before forwarding each message. this prevents timing-based traffic analysis.
> relay protocol
the relay speaks a simple JSON protocol over WebSocket. it understands 5 message types but cannot read the contents of any encrypted payload.
client → relay
relay → client
relay limits
> proof-of-work
every message requires a hashcash-style proof-of-work before it can be sent. this prevents spam and forms the basis for $LIME token rewards.
how it works
the message payload (id, author, content, board, thread, timestamp) is serialized to canonical JSON. the client iterates nonces until SHA-256(payload || nonce) has at least 20 leading zero bits. this takes roughly 1-2 seconds.
// PoW algorithm
payload = canonical_json(id, author, content, board, thread, timestamp)
nonce = 0
loop:
hash = SHA-256(payload || nonce_bytes)
if hash < 2^(256 - 20): // 20 leading zero bits
return (nonce, hash)
nonce += 1
> $LIME token & vault
$LIME is an ERC-20 token on Base L2, deployed via Clanker. 30% of the total supply (300M LIME) is held in the LimesVault smart contract, which handles staking, rewards, and board governance.
staking
relay operators must stake at least 250,000 LIME to the LimesVault to register as an active relay. staking gives them the right to claim PoW rewards and vote on board proposals. unstaking requires a 7-day cooldown to prevent flash-stake attacks.
rewards
when a relay operator forwards a message, they can submit the PoW proof (payload + nonce) to the vault's claimReward() function. the vault verifies the proof on-chain and sends 1.0 LIME from the pool. each proof can only be claimed once. only staked relay operators can claim. message senders do not earn tokens.
supply math
the vault holds 300M LIME. at 1 LIME per proof, the pool sustains 300 million messages before depletion. at 1,000 messages per day network-wide, that's ~822 years of rewards.
board governance
staked relay operators can call proposeBoard("name") on the vault contract. each relay gets one vote. when 3 relays have voted for a board, it's approved and goes live for all peers. /general/ is approved by default at deployment.
> security model
what is protected
known limitations
threat model
limes's privacy model is similar to Bitcoin: transactions (messages) are public, identities are pseudonymous, and nodes (relays) see connecting IPs but cannot determine which IP sent which message thanks to gossip propagation and timing obfuscation. for stronger IP privacy, route through Tor.
> CLI & chat commands
CLI commands
chat commands (in TUI)
TUI keybindings
> FAQ
is limes safe for my friends to use?
yes. messages are end-to-end encrypted through relays, identities are pseudonymous, and everything is ephemeral. no accounts, no data stored. the worst case is someone on the same relay sees your IP address — use a VPN if that concerns you.
is it safe to run a relay?
yes. relays forward encrypted blobs they cannot read. they don't store anything, don't execute code from messages, and don't access your filesystem. the relay is hardened with connection limits, rate limits, and message size caps.
is this like 4chan?
similar concept — anonymous boards with threads — but more private. on 4chan, your IP is visible to admins and your posts are archived forever. on limes, relay operators can't link your IP to your pseudonym, all messages are e2e encrypted in transit, and everything disappears after 24 minutes. no archives, no logs, no trace.
what happens after 24 minutes?
messages are stored only in RAM on connected peers. after 24 minutes, they are pruned and gone forever. no relay, no server, no database ever stores them. when all messages in a thread expire, the thread vanishes too.
can someone impersonate me?
every message is signed with your Ed25519 private key. forging a signature is computationally infeasible. however, pseudonyms are not globally unique — someone could pick the same name in a different session. the #tag (derived from the public key) helps distinguish identities.
how do relay operators earn?
relay operators stake 250,000 LIME to register on-chain. for every message they forward, they can submit the PoW proof to the LimesVault and receive 1.0 LIME from the reward pool. the pool holds 300M LIME (30% of supply), which lasts effectively forever at normal usage.