@arg@twtpub.com You actually can, but we highly discourage it and I haven’t really built “Edit” / “Delete” functionality in the Twtxt App that I know you’re using 😅 Twtxt being purely decentralised, meaning that there are absolutely zero decentralised, with the exception of the twtpub.com service you’re using to reduce as much friction as possible for newcomers to try things, makes supporting threads a bit of a controversial topic 😆 – In the end we are sticking with the Hash v2 extension, making threads use content addressing, so even if you did delete/edit a Twt, you have to be carefuly it hasn’t already been replied to in the ecosystem 🤣
@prologic@twtxt.net No. After the cutoff-date, hashes are expected to be v2. End of story.
(In jenny, a twt can only ever have one thing that can be used for threading.)
@david@daiwei.me This is another dangling thread:
Trying to fetch "#kyjhiwcxeknm" from Yarn pod https://txt.sour.is ...
Trying to fetch "#kyjhiwcxeknm" from Yarn pod https://twtxt.net ...
Twt could not be found
+00:00 vs Z should be treated as equivalent UTC 🤦♂️ I'll take a look at the timestamp parsing in Yarnd 🧐
@prologic@twtxt.net For what it’s worth, the twt hash extension is specifically modeled after yarnd’s implementation with all the quirks coming from Go’s stdlib: https://twtxt.dev/exts/twt-hash.html#timestamp-format
“All timezones representing UTC must be formatted using the designated Zulu indicator Z rather than the numeric offsets +00:00 or -00:00. If the timestamp does not explicitly include any timezone information, it must be assumed to be in UTC.”
🥳 Finally! After nearly 4 years, yarnd v0.16.0 “Silver Sojourner” is out! 🚀 Twt Hash v2, SQLite FTS5 search, HTMX-powered UI, first-time setup wizard and literally hundreds of bug fixes 🐛
Release notes: https://git.mills.io/yarnsocial/yarn/releases/tag/0.16.0
Upgrading is fully automatic — the Twt Hash v2 migration re-fetches all feeds on first start, so expect the first cycle to be a bit heavier. Images on Docker Hub as prologic/yarnd:0.16.0 👌
cc @kat@yarn.girlonthemoon.xyz @abucci@anthony.buc.ci @shinyoukai@yume.laidback.moe @eldersnake@we.loveprivacy.club 🙏
Yeah to @david@daiwei.me’s point re Editing. It’s only really safe to do so if you are sure that no-one has yet fetched your feed or replied to your Twt. But even then, you have to be quick 🤣 Editing/fixing a Twt inside of an existing thread is “oaky”, as long as it also doesn’t get forked and becomes the root of a new conversation 😅
@bender@twtxt.net All the other ones worked but this broke? What’s different here? To which twt hash should this be a reply? 🤔
@bender@twtxt.net Ah, the first twts were from https://raw.githubusercontent.com/Fastidious/fastidious.github.com/master/twtxt.txt, not https://daiwei.me/twtxt.txt. Fetching the GitHub feed completes the thread. 👍
Fixed the broken hashes in the Twtxt App (https://twtxt.app) 🥳 It was hashing your twts with a client-side timestamp the server never used 🤦♂️ Now it keeps the canonical created/hash the pod (or twtd) returns, and the GitHub/Gitea backends write a # url = preamble so every client hashes your feed the same way. Thanks @fastidious@tilde.town for the report 🙏
@prologic@twtxt.net I linked you some of my findings on the twtxt.app on IRC. The main problem is the hashing. Totally broken. But you have got to give it some thought, because GitHub hosting of the feed is tricky (even more so if they are CNAMEing their domain to it). It is also finicky because Pages is auto-enabled on username.github.io, so actions must run each time you twt.
@bender@twtxt.net “Twt could not be found” 😢
lleeypvkzbw2? That Twt was never ingested by twtxt.net (and likely the search engine) so umm hmmm threading breaks 🤣
@GabesArcade@gabesarcade.com Yes, because if you edit/delete a Twt after the ecosystem has ingested it, well there then are two versions 😅 Just be aware of edits/deletes, especially if someone has already replied to said Twt 🤣
@GabesArcade@gabesarcade.com Did you by change edit or otherwise delete the Twt you replied to (2nd last in your feed) with the reply/thread id lleeypvkzbw2? That Twt was never ingested by twtxt.net (and likely the search engine) so umm hmmm threading breaks 🤣
@javivf@adn.org.es Heh! 😏 I don’t get it haha, but I just saw your post about supporting the v2 Hash ext, nice! 👍
@balloonfu-sen@yarn.girlonthemoon.xyz Do you mind git pull && make build and updating your yarnd instance so it’s in-line with the new Hash v2 spec 🙏
@GabesArcade@gabesarcade.com’s Arcade@gabesarcade.com You will want to either build a client or use one of the ones listed here – Either way you choose! 👌 I just noticed as well in this Twt I’m replying to (threading is a thing™) that you @-mentioned@twtxt.net @bender@twtxt.net incorrectly 😅
@prologic@twtxt.net this was supposed to be a reply to this, not sure how it ended up all there, by itself, sad and lonely. 😅
Well well well, the big twtxt-hash version change took place and with just two lines of code I hope, I covered it up in my fiddely little webclient. houseplant programming 🪴
Set/GetDisabled(…) and PasteHandler(), tt starts up fine and seems to work without issues.
Haha, I just noticed that this is the first twt hash v2 that I reply to. \o/ Oh yeah!
I was wondering why all the twt hashes in my replies today were still so short. I was ahead of the times. The Twt Hash v2 Epoch only begins next month.
@itsericwoodward@itsericwoodward.com Excited to see twtxt tooling in the Node ecosystem! Any plans to implement the Twtxt v2 extensions? Things like Twt Hash + Subject (proper threading), Multiline, etc. — all documented at https://twtxt.dev 👀
yey! I remembered how to prune my Jenny/Neomutt Twtxt feed! (I only keep 6 months worth of Twts) Now, I need to figure out how to set up a macro for that.
@thecanine@twtxt.net are you referring to the “WE FUCKING WON!” twtxt?
yarnd had no reason to "pull" it in.
@bender@twtxt.net Only missing roots would trigger that kind of sync IIRC. And that only works if another peering pod has the root twt. What you’re remembering, possibly, is an attempt to do what you were thinking of… But I tried it, turned out to be too expensive of an operation to do auotmatically.
@movq@www.uninformativ.de that some lovely development from the initial one. Curious to know where this will lead!
@klaxzy@klaxzy.net nothing like a blank twt eh? 😅
@zvava@twtxt.net By hashing definition, if you edit your message, it simply becomes a new message. It’s just not the same message anymore. At least from a technical point of view. As a human, personally I disagree, but that’s what I’m stuck with. There’s no reliable way to detect and “correct” for that.
Storing the hash in your database doesn’t prevent you from switching to another hashing implementation later on. As of now, message creation timestamps earlier than some magical point in time use twt hash v1, messages on or after that magical timestamp use twt hash v2. So, a message either has a v1 or a v2 hash, but not both. At least one of them is never meaningful.
Once you “upgrade” your database schema, you can check for stored messages from the future which should have been hashed using v2, but were actually v1-hashed and simply fix them.
If there will ever be another addressing scheme, you could reuse the existing hash column if it supersedes the v1/v2 hashes. Otherwise, a new column might be useful, or perhaps no column at all (looking at location-based addressing or how it was called). The old v1/v2 hashes are still needed for all past conversation trees.
In my opinion, always recalculating the hashes is a big waste of time and energy. But if it serves you well, then go for it.
Hmmmm the AoC site is not mobile friendly 😢
Can someone post the puzzles as Twts? 🤣
@lyse@lyse.isobeef.org Damn. That was stupid of me. I should have posted examples using 2026-03-01 as cutoff date. 😂
In my actual test suite, everything uses 2027-01-01 and then I have this, hoping that that’s good enough. 🥴
def test_rollover():
d = jenny.HASHV2_CUTOFF_DATE
assert len(jenny.make_twt_hash(URL, d - timedelta(days=7), TEXT)) == 7
assert len(jenny.make_twt_hash(URL, d - timedelta(seconds=3), TEXT)) == 7
assert len(jenny.make_twt_hash(URL, d - timedelta(seconds=2), TEXT)) == 7
assert len(jenny.make_twt_hash(URL, d - timedelta(seconds=1), TEXT)) == 7
assert len(jenny.make_twt_hash(URL, d, TEXT)) == 12
assert len(jenny.make_twt_hash(URL, d + timedelta(seconds=1), TEXT)) == 12
assert len(jenny.make_twt_hash(URL, d + timedelta(seconds=2), TEXT)) == 12
assert len(jenny.make_twt_hash(URL, d + timedelta(seconds=3), TEXT)) == 12
assert len(jenny.make_twt_hash(URL, d + timedelta(days=7), TEXT)) == 12
(In other words, I don’t care as long as it’s before 2027-01-01. 😏😅)
@shinyoukai@neko.laidback.moe What do you mean by that? 🧐 Clients don’t care about the order of twts in a feed. For display clients usually sort by timestamp.
Oh my god! 🤣 It works! 🥳 My first Twt into the Fediverse (stil some improvements to be made of course), but still 😳 Wow! 🤩 
All my newly added test cases failed, that movq thankfully provided in https://git.mills.io/yarnsocial/twtxt.dev/pulls/28#issuecomment-20801 for the draft of the twt hash v2 extension. The first error was easy to see in the diff. The hashes were way too long. You’ve already guessed it, I had cut the hash from the twelfth character towards the end instead of taking the first twelve characters: hash[12:] instead of hash[:12].
After fixing this rookie mistake, the tests still all failed. Hmmm. Did I still cut the wrong twelve characters? :-? I even checked the Go reference implementation in the document itself. But it read basically the same as mine. Strange, what the heck is going on here?
Turns out that my vim replacements to transform the Python code into Go code butchered all the URLs. ;-) The order of operations matters. I first replaced the equals with colons for the subtest struct fields and then wanted to transform the RFC 3339 timestamp strings to time.Date(…) calls. So, I replaced the colons in the time with commas and spaces. Hence, my URLs then also all read https, //example.com/twtxt.txt.
But that was it. All test green. \o/
Hmmm, looks like my twt hash algorithm implementation calculates incorrect values. Might be the tilde in the URL that throws something off. :-? At least yarnd and jenny agree on a different hash.
@threatcat@tilde.club unwritten etiquette (by me, and for me, but one can hope, right?).
- Proper grammar (in any language).
- Correct capitalisation, and punctuation.
- Subject extension support.
Anything else doesn’t matter. ☺️
@bender@twtxt.net You are totally correct! The thing is: The Caveman within was thinking how minimal can one go before things start to get too uncomfortable? And if cavemen weren’t supposed to be too self-conscious about their spelling, I could have just ssh remote echo "$(date -Is)\tTwt Twt Mother-Lover! 🤣🤣" >> /path/to/twtxt.txt and called it a day.
@aelaraji@aelaraji.com yeah, it looks tedious because it is. LOL. I can twt no matter where I am because a) with Yarn is as easy as opening a web browser, and b) with jenny is as easy at SSHing to my VPS. But, the keyword is fun. That’s what matters!
Just typing twts directly into my twtxt file.
Details:
- Opening my twtxt file remotely using
vim scp://user@remote:port//path/to/twtxt.txt
- Inserting the date, time and tab part of the twt with
:.!echo "$(date -Is)\t"
- In case I need to add a new line I just
Ctrl+Shift+u, type in the2028and hitEnter
- In order to replay, you just steal a twt hash from your favorite Yarn instance.
It looks tedious, but it’s fun to know I can twt no matter where I am, as long as can ssh in.
Holly! I thing I might have figured out a way to twt like a true caveman 🤣
The sad thing tho is this caveman will have to cheat a bit in order to replay properly…
(P.S: I hope the multi-lines trick works, if not then F..rog it!)
I meant, “jlj”. He used to be at https://twt.nfld.uk/, long gone now too. I wonder…
@alexonit@twtxt.alessandrocutolo.it Yeah I think we’re overstating the UNIX principles a bit here 🤣 I get what you’re trying to say though @zvava@twtxt.net 😅 If I could go back in time and do it all over again, I would have gotten the Hash length correct and I would have used SHA-256 instead. But someone way smarter than me designed the Twt Hash spec, we adopted it and well here we are today, it works™ 😅
plus, if hashv2 was implemented in combination with text fragments the way you proposed that would solve both scripting and human readability woes!!
…though, the presence of the text fragments then makes reversing the replied-to twt (and therefore its hash) trivial, which could allow clients to tolerate the omission of the hash — and while it would be ‘non-standard’ this would be the best of both worlds; potential to tolerate (or pave a glacial path toward? :o) human writable replies whilst keeping a unique id for twts that is universal across all pods
@zvava@twtxt.net Going to have to hard disagree here I’m sorry. a) no-one reads the raw/plain twtxt.txt files, the only time you do is to debug something, or have a stick beak at the comments which most clients will strip out and ignore and b) I’m sorry you’ve completely lost me! I’m old enough to pre-date before Linux became popular, so I’m not sure what UNIX principles you think are being broken or violated by having a Twt Subject (Subject) whose contents is a cryptographic content-addressable hash of the “thing”™ you’re replying to and forming a chain of other replies (a thread).
I’m sorry, but the simplest thing to do is to make the smallest number of changes to the Spec as possible and all agree on a “Magic Date” for which our clients use the modified function(s).
Nothing serious! just a sanity check Twt x) ...
@kat@yarn.girlonthemoon.xyz Mine shows 1/1 of 14 Twts 😆 I think this is a bug 🤯
whyyyyy is my discover page only showing 7 twts!!!
🧮 USERS:1 FEEDS:2 TWTS:1470 ARCHIVED:90004 CACHE:2669 FOLLOWERS:22 FOLLOWING:14
🧮 USERS:1 FEEDS:2 TWTS:1469 ARCHIVED:89989 CACHE:2669 FOLLOWERS:22 FOLLOWING:14
🧮 USERS:1 FEEDS:2 TWTS:1468 ARCHIVED:89982 CACHE:2683 FOLLOWERS:22 FOLLOWING:14
🧮 USERS:1 FEEDS:2 TWTS:1467 ARCHIVED:89975 CACHE:2680 FOLLOWERS:22 FOLLOWING:14
🧮 USERS:1 FEEDS:2 TWTS:1466 ARCHIVED:89964 CACHE:2691 FOLLOWERS:22 FOLLOWING:14
🧮 USERS:1 FEEDS:2 TWTS:1465 ARCHIVED:89956 CACHE:2696 FOLLOWERS:22 FOLLOWING:14
@lyse@lyse.isobeef.org i dont mind if the hash is not backward compatible but im not sure if this is the right way to proceed because the added complexity dealing with two hash versions isnt justified
regular end users wont care to understand how twt hashes are formed, they just want to use twtxt! so i guess i could work in protecting users from themselves by disallowing post edits on old posts or posts with replies, but i’m not fond of this either really. if they want to break a thread, they can just delete the post (though i’ve noticed yarn handling post deletes dubiously…)
on activitypub i do genuinely find myself looking through several month or even year old posts sometimes and deciding to edit/reword them a little to be slightly less confusing, this should be trivial to handle on twtxt which is an infinitely simpler specification
🧮 USERS:1 FEEDS:2 TWTS:1464 ARCHIVED:89943 CACHE:2694 FOLLOWERS:22 FOLLOWING:14
ok so i have found a genuine twt hash collision. what do i do.
internally, bbycll relies on a post lookup table with post hashes as keys, this is really fast but i knew i’d inevitably run into this issue (just not so soon) so now i have to either:
1) pick the newer post over the other
2) break from specification and not lowercase hashes
3) secretly associate canonical urls or additional entropy with post hashes in the backend without a sizeable performance impact somehow

🧮 USERS:1 FEEDS:2 TWTS:1463 ARCHIVED:89933 CACHE:2719 FOLLOWERS:22 FOLLOWING:14
🧮 USERS:1 FEEDS:2 TWTS:1462 ARCHIVED:89926 CACHE:2715 FOLLOWERS:22 FOLLOWING:14
🧮 USERS:1 FEEDS:2 TWTS:1461 ARCHIVED:89907 CACHE:2729 FOLLOWERS:22 FOLLOWING:14
@lyse@lyse.isobeef.org retwts are a discovery feature! on federated platforms with no algorithm where you only ever see posts from accounts you explicitly follow, the element of “hey look at this!” helps users to find other accounts they might like organically
i agree quoting and replying forum-style is generally a much better way of doing things even though im a heathen and i revel in the dark patterns inspired by quote posts but when you have nothing to add and you just want to share a twt with your followers it’d be good to have a standardized way of linking to twt
🧮 USERS:1 FEEDS:2 TWTS:1460 ARCHIVED:89905 CACHE:2731 FOLLOWERS:22 FOLLOWING:14
🧮 USERS:1 FEEDS:2 TWTS:1459 ARCHIVED:89894 CACHE:2727 FOLLOWERS:22 FOLLOWING:14
at first i dismissed the idea of likes on twtxt as not sensible…like at all — then i considered they could just be published in a metadata field (though that field could get really unruly after a while)
retwts are plausible, as “RE: https://example.com/twtxt.txt#abcdefg”, the hash could even be the original timestamp from the feed to make it human readable/writable, though im extremely wary of clogging up timelines
i thought quote twts could be done extremely sensibly, by interpreting a mention+hash at the end of the twt differently to when placed at the beginning — but the twt subject extension requires it be at the beginning, so the clean fallback to a normal reply i originally imagined is out of the question — it could still be possible (reusing the retwt format, just like twitter!) but i’m not convinced it’s worth it at that point
is any of this in the spirit of twtxt? no, not in the slightest, lmao
🧮 USERS:1 FEEDS:2 TWTS:1458 ARCHIVED:89883 CACHE:2723 FOLLOWERS:22 FOLLOWING:14
Oops, maybe I should have posted a reminder. 🥴
@dce@hashnix.club By the time you posted your twt, the red phase was already over. 🙈 Stellarium has a pretty good simulation of the whole thing.
🧮 USERS:1 FEEDS:2 TWTS:1457 ARCHIVED:89869 CACHE:2715 FOLLOWERS:22 FOLLOWING:14
🧮 USERS:1 FEEDS:2 TWTS:1456 ARCHIVED:89837 CACHE:2703 FOLLOWERS:22 FOLLOWING:14
🧮 USERS:1 FEEDS:2 TWTS:1455 ARCHIVED:89815 CACHE:2688 FOLLOWERS:22 FOLLOWING:14
🧮 USERS:1 FEEDS:2 TWTS:1454 ARCHIVED:89800 CACHE:2675 FOLLOWERS:22 FOLLOWING:14
🧮 USERS:1 FEEDS:2 TWTS:1453 ARCHIVED:89786 CACHE:2676 FOLLOWERS:22 FOLLOWING:14
🧮 USERS:1 FEEDS:2 TWTS:1452 ARCHIVED:89778 CACHE:2673 FOLLOWERS:22 FOLLOWING:14
🧮 USERS:1 FEEDS:2 TWTS:1451 ARCHIVED:89768 CACHE:2666 FOLLOWERS:22 FOLLOWING:14
🧮 USERS:1 FEEDS:2 TWTS:1450 ARCHIVED:89755 CACHE:2658 FOLLOWERS:22 FOLLOWING:14
🧮 USERS:1 FEEDS:2 TWTS:1449 ARCHIVED:89735 CACHE:2650 FOLLOWERS:22 FOLLOWING:14
🧮 USERS:1 FEEDS:2 TWTS:1448 ARCHIVED:89727 CACHE:2644 FOLLOWERS:22 FOLLOWING:14
🧮 USERS:1 FEEDS:2 TWTS:1447 ARCHIVED:89714 CACHE:2638 FOLLOWERS:22 FOLLOWING:14
🧮 USERS:1 FEEDS:2 TWTS:1446 ARCHIVED:89680 CACHE:2640 FOLLOWERS:22 FOLLOWING:14
🧮 USERS:1 FEEDS:2 TWTS:1445 ARCHIVED:89665 CACHE:2626 FOLLOWERS:22 FOLLOWING:14
🧮 USERS:1 FEEDS:2 TWTS:1444 ARCHIVED:89656 CACHE:2618 FOLLOWERS:22 FOLLOWING:14
🧮 USERS:1 FEEDS:2 TWTS:1443 ARCHIVED:89640 CACHE:2613 FOLLOWERS:22 FOLLOWING:14
🧮 USERS:1 FEEDS:2 TWTS:1442 ARCHIVED:89622 CACHE:2606 FOLLOWERS:22 FOLLOWING:14
🧮 USERS:1 FEEDS:2 TWTS:1441 ARCHIVED:89619 CACHE:2612 FOLLOWERS:22 FOLLOWING:14
🧮 USERS:1 FEEDS:2 TWTS:1440 ARCHIVED:89613 CACHE:2612 FOLLOWERS:22 FOLLOWING:14
🧮 USERS:1 FEEDS:2 TWTS:1439 ARCHIVED:89607 CACHE:2612 FOLLOWERS:22 FOLLOWING:14
🧮 USERS:1 FEEDS:2 TWTS:1438 ARCHIVED:89599 CACHE:2610 FOLLOWERS:22 FOLLOWING:14
🧮 USERS:1 FEEDS:2 TWTS:1437 ARCHIVED:89595 CACHE:2607 FOLLOWERS:22 FOLLOWING:14
🧮 USERS:1 FEEDS:2 TWTS:1436 ARCHIVED:89590 CACHE:2613 FOLLOWERS:22 FOLLOWING:14
🧮 USERS:1 FEEDS:2 TWTS:1435 ARCHIVED:89587 CACHE:2614 FOLLOWERS:22 FOLLOWING:14
🧮 USERS:1 FEEDS:2 TWTS:1434 ARCHIVED:89577 CACHE:2615 FOLLOWERS:22 FOLLOWING:14
🧮 USERS:1 FEEDS:2 TWTS:1433 ARCHIVED:89576 CACHE:2615 FOLLOWERS:22 FOLLOWING:14
🧮 USERS:1 FEEDS:2 TWTS:1432 ARCHIVED:89571 CACHE:2612 FOLLOWERS:22 FOLLOWING:14
🧮 USERS:1 FEEDS:2 TWTS:1431 ARCHIVED:89562 CACHE:2642 FOLLOWERS:22 FOLLOWING:14
🧮 USERS:1 FEEDS:2 TWTS:1430 ARCHIVED:89185 CACHE:2622 FOLLOWERS:22 FOLLOWING:14
🧮 USERS:1 FEEDS:2 TWTS:1429 ARCHIVED:89174 CACHE:2643 FOLLOWERS:22 FOLLOWING:14
🧮 USERS:1 FEEDS:2 TWTS:1428 ARCHIVED:89170 CACHE:2645 FOLLOWERS:22 FOLLOWING:14
🧮 USERS:1 FEEDS:2 TWTS:1427 ARCHIVED:89169 CACHE:2645 FOLLOWERS:22 FOLLOWING:14
🧮 USERS:1 FEEDS:2 TWTS:1426 ARCHIVED:89109 CACHE:2646 FOLLOWERS:22 FOLLOWING:14
🧮 USERS:1 FEEDS:2 TWTS:1425 ARCHIVED:89098 CACHE:2646 FOLLOWERS:22 FOLLOWING:14
🧮 USERS:1 FEEDS:2 TWTS:1424 ARCHIVED:89083 CACHE:2639 FOLLOWERS:22 FOLLOWING:14
🧮 USERS:1 FEEDS:2 TWTS:1423 ARCHIVED:89080 CACHE:2639 FOLLOWERS:22 FOLLOWING:14
🧮 USERS:1 FEEDS:2 TWTS:1422 ARCHIVED:89079 CACHE:2639 FOLLOWERS:22 FOLLOWING:14