AT Protocol / Bluesky client in gforth. The interpreter is the UI.
forthsky 0.1 — AT Protocol client in gforth
Former Lab. GPL v3. Type `help` for words, `login` to begin.
ok login
handle: formerlab.bsky.social
app password: ****
✓ session established for @formerlab.bsky.social
ok 5 timeline
[1] @nintendolife.com 2026-05-15T10:25:01+01:00
Tomodachi Life: Living The Dream Updated To Version 1.0.2,
Here Are The Full Patch Notes. (Repost)
♥ 0 ↻ 0
[2] @patak.cat 2026-05-15T09:24:49.365Z
oh, thanks! I reposted it in english. I have no idea why the
mobile app defaulted to german
♥ 0 ↻ 0
...
ok 1 like
✓ liked.
ok s" hello from Forth and Forthsky" post
✓ posted.
at://did:plc:.../app.bsky.feed.post/3mluvf...
ok bye
There is no main loop. There are no menus. Words compose. Lists on screen are addressable by index. 1 like likes the first thing you just rendered — like Forth always works, the previous thing becomes input to the next thing.
┌────────────────┐ plain HTTP/1.0 ┌──────────────────┐ HTTPS ┌──────────────┐
│ gforth bsky.fs │ ─────────────────▶│ forthsky-bridge │ ───────▶ │ PDS │
│ (Forthsky) │ │ (socat+OpenSSL) │ │ bsky.social │
└────────────────┘ 127.0.0.1:8443 └──────────────────┘ :443 └──────────────┘
Forth handles the application protocol. A short socat sidecar terminates TLS and forwards bytes to the PDS. Honest about what it is — no embedded crypto stack yet, just a clean line between protocol logic (Forth) and ciphers (OpenSSL via socat).
v0.1 Posts to the live network. Read and write paths
verified against bsky.social.
Implemented: login, whoami, logout, N timeline, s" text" post,
N like, N repost, real ISO-8601 timestamps via date -u.
Coming next:
-
N thread— show a post and its replies -
N reply <text>— reply to a feed item -
N profile— author profile of an item -
N follow/N unfollow -
notifications/search - Better repost/quote-post detection in timeline parse
- Pure-Forth ed25519 + DPoP + full OAuth (replaces app passwords)
- Firehose subscriber + sine-scroller demoscene moment
Tested on Ubuntu 25.10. Should work anywhere gforth and socat run.
# 1. install deps
sudo apt install -y gforth socat libtool libtool-bin libc6-dev build-essential
# 2. clone
git clone https://github.com/FormerLab/forthsky.git
cd forthsky
# 3. make the bridge executable
chmod +x bridge/forthsky-bridge.sh
# 4. start the TLS bridge in one terminal
./bridge/forthsky-bridge.sh
# 5. start forthsky in another
LC_ALL=en_US.UTF-8 gforth bsky.fsThe LC_ALL matters: gforth 0.7.3 needs a UTF-8 locale active for xc@+
to decode codepoints correctly.
For credentials, use a Bluesky app password (Settings → App Passwords), not your main account password.
session: login whoami logout
reading: N timeline (planned: N thread, N profile)
writing: s" text" post N like N repost
(planned: N reply <text>)
misc: help bye
N is the 1-based index from the last rendered list.
gforth 0.7.3 quirks worth knowing if you want to extend Forthsky:
xc@+ ( addr -- addr' xc )— single address in, manage byte counts withxc-size.require utf-8.fs+set-encoding-utf-8is mandatory for codepoint mode.+todoesn't exist; usedup toor plain variables with+!.\starts a line comment; for a backslash byte literal use92(its ASCII).- Names are case-insensitive — don't define
FOOconstant andfoovariable. [char] X foonotfoo [char] X— literal-then-word, as for any Forth word.cmove ( src dst u -- ), easy to flip with theaddr ustring convention.- Locals (
{ ... -- ... }) save you from stack juggling; use them in any word with more than three live values. - bsky.social returns chunked HTTP/1.1 by default; Forthsky speaks HTTP/1.0 to avoid implementing chunk decoding.
The hardest parts (display width + word wrap, JSON SAX, JSON-path matching,
the field-extraction routing in xrpc.fs) are done and verified against
the live network. New verbs are short additions to xrpc.fs.
GPL v3.
Forthsky is one of an esoteric/retro AT Protocol client series from Former Lab — building sovereign computing infrastructure. Other clients in the series:
- Fortransky — Fortran 2018, dithering and DM support
- Cobolsky — GnuCOBOL 3.1, Floyd-Steinberg in pure COBOL (COMING SOON)
- Assemblersky500 — 68000 assembly, Linux m68k + AmigaOS dual target (COMING SOON)
- INTERCALsky — yes, really
- Malbolgesky — yes, really
- Adatalksky - Ada and Smalltalk
The series is proof-of-work for a broader thesis: anything that touches the network should be expressible in any sufficient language, on any sufficient machine, including the deliberately inadequate ones.