@lyse@lyse.isobeef.org It reads a lot nicer, yeah. And you can do oink.my_property += 1 as well, for example.
Hurray, I can now press gg instead of g to go to the top in tt. Much better! :-) Other multi-key combinations are also easily possible now.
I should probably write a real article about this at some point, but here we go. The only downside with my new key binding system is that it breaks tviewās established pattern. Youāve got an InputHandler(), that is implemented using WrapInputHandler(ā¦). It typically then directly implements the switching logic depending on the key press. Something like this:
func (w *Widget) InputHandler() func(event *tcell.EventKey, setFocus func(p tview.Primitive)) {
// WrapInputHandler allows for intercepting key events with SetInputCapture(ā¦)
// from the outside for customization. This handles the default key bindings.
return t.WrapInputHandler(func(event *tcell.EventKey, setFocus func(p tview.Primitive)) {
switch event.Key() {
case tcell.KeyRune:
if event.Modifiers() == tcell.ModNone {
switch event.Rune() {
case 'k':
w.scrollUp()
return // we already handled the event, stop processing
case 'j':
w.scrollDown()
return
}
}
}
// We didn't handle the key event. Maybe the parent
// widget knows what to do with it.
if handler := w.parent.InputHandler(); handler != nil {
handler(event, setFocus)
}
})
}
From the outside, you can intercept and either stop or continue the widgetās original key handling with a potentially rewritten key event using SetInputCapture(ā¦):
w := NewWidget()
// customized or additional key bindings
w.SetInputCapture(func(event *tcell.EventKey) *tcell.EventKey {
switch event.Key() {
case tcell.KeyUp:
// Rewrite the event, so the "cursor up" key is an alias
// for the vim key binding "k", that is handled by the
// wrapped input handler above. (I know, I know, this is a
// completely unrealistic example, why would anyone use
// cursor keys when there are vim key bindings available?!)
return tcell.NewEventKey(tcell.KeyRune, 'k', tcell.ModNone)
case tcell.KeyRune:
if event.Modifiers() == tcell.ModNone {
switch event.Rune() {
case 'q':
app.Stop()
// we already handled the event, do not pass it
// to the wrapped input handler above
return nil
case 'r':
toggleMessageReadStatus()
return nil
}
}
}
// we didn't handle the event, pass it to the wrapped
// input handler above
return event
}
Since they all expect a single key, Iāve noticed that using multiple dedicated KeyBindings of mine on these different levels kinda breaks multi-key handling with common prefixes. The outer-most KeyBinding captures the prefix, but it canāt transfer it to the inner one if not handled by the outer one. At least not without some more (potentially ugly) changes. So, I now have to work with just a single KeyBindings object for the entire widget chain (if it consists of multiple other widgets or the regular input handler and input capture are in the game). The outside needs to register all its key bind customizations or extensions at the same level that the original widget handles its default ones. Doable by exposing the widgetās KeyBindings instance, but not pretty. You always have to keep this in mind.
With the KeyBindings, it will look like that:
type Widget struct {
parent tview.Primitive
// make it available to children or the outside either by
// direct field access or by providing a getter method
KeyBindings *bind.KeyBindings
}
func NewWidget() *Widget {
w := &Widget{KeyBindings: &bind.KeyBindings{}}
w.KeyBindings. // default key bindings
Bind0(bind.KeySequence('k', w.scrollUp).
Bind0(bind.KeySequence('j', w.scrollDown)
return w
}
func (w *Widget) InputHandler() InputHandler() func(event *tcell.EventKey, setFocus func(p tview.Primitive)) {
return t.WrapInputHandler(func(event *tcell.EventKey, setFocus func(p tview.Primitive)) {
// also note the missing support for focus transfer at the moment
event = w.KeyBindings.Capture(event)
if event == nil {
return
}
if handler := w.parent.InputHandler(); handler != nil {
handler(event, setFocus)
}
}
}
And then from the outside, or in a child widget:
w := NewWidget()
w.KeyBindings. // additional or customized key bindings
Bind1(bind.KeySequence(tcell.KeyUp), func(*tcell.EventKey) *tcell.EventKey {
return tcell.NewEventKey(tcell.KeyRune, 'k', tcell.ModNone)
}).
Bind0(bind.KeySequence('q'), app.Stop).
Bind0(bind.KeySequence('r'), toggleMessageReadStatus)
When directly working with tview primitives that are not part of custom widget implementations, the following works well so far:
textView := tview.NewTextView().
SetWordWrap(true).
SetText("ā¦")
SetScrollable(true)
textView.SetInputCapture((&bind.KeyBindings{}).
Bind0(bind.KeySequence('q'), app.Stop).
Bind1(bind.KeySequence('g', 'g'), func(*tcell.EventKey) *tcell.EventKey {
return tcell.NewEventKey(tcell.KeyHome, 0, tcell.ModNone)
}).
Capture)
I need to sleep on this some more.
Also, writing very long messages like this one is really not all that fun in ttās editor. I should absolutely provide a way to shell out to vim.
(Took me about one and a half hours to compose, holy crap. But not only because of not using vim. Although, that might have saved me a quarter hour or so for sure. Proof-reading this message also uncovered quite a few bugs in my real documentation. So, thatās a big win!) Good night!
there is for example, a user configurable and default instance configuration called only one postponed domain
As an example, this is a thread @GabesArcade@gabesarcade.comās Arcade@gabesarcade.com and @david@daiwei.me carried all on twtxt.app, no issues: https://twtxt.net/conv/r4uf52ggwseh
@lyse@lyse.isobeef.org This apparently depends on the program now ⦠Some Qt6 programs still allow that, others donāt. I canāt remember if GTK ever had that feature. š¤ But yeah, this whole āmove stuff around as you pleaseā-mentality is mostly gone.
I know I keep referring to StarOffice 3.1 a lot, but itās just such a good example for all these things. All the toolbars and panels could be rearranged:

(This is running in Wine, btw.)
LibreOffice is the descendant of StarOffice and it doesnāt support anything like that anymore.
Maybe it was deemed too confusing for users? āOh no, I mis-clicked something and now that bar is gone! How do I get it back? I donāt even know what itās called!ā š¤
@bender@twtxt.net I know heat (Iāve been to Southeast Asia, for example ā or Florida š¤£), but youāre right, it does hit very differently when itās at home. āAt homeā is usually the cool and relaxed place, but now itās hell. And no AC anywhere in sight.
New project in the works. Federated game network and a new LoRD-inspired game as teh example⦠stay tuned!
The web never needed scripting, and Gopher is the greatest example of it.
@movq@www.uninformativ.de Yeah, that would also be fine with me. I certainly do like the āarbitraryā in your comment.
While writing the article, I also thought about something like that:
date := time.Date(2026, 6, 19,
17, 0, 0, 0, time.UTC)
Or possibly:
date := time.Date(
2026, 6, 19,
17, 0, 0, 0, time.UTC,
)
But itās four lines for a damn timestamp. I also contemplated whether a comment acting as a separator is all thatās needed:
date := time.Date(2026, 6, 19, /**/ 17, 0, 0, 0, time.UTC)
I might like that the most. Not entirely sure yet. It kinda feels like a hack, but still a little elegant. Add your comment on top and weāre golden. Maybe?
I deliberately excluded them as this only distracted from the points I wanted to make. And I also realized that this example was just not ideal at all. Perhaps I should add them nevertheless?
If I ever invented a programming language, a much more human readable timestamp representation of some sort, RFC 3339 or very close to that would be part of that language. Something along the lines of /pattern/ for regexes in certain languages.
tt. But then, in the message tree, I spot another missed typo. My process is then to go to my twtxt.txt and fix it by hand. However, I still have to clean up tt's cache. This is rather tidious:
With multicolored TUIs, I find it usually hard to immediately tell which button is selected if there are just two.
Indeed, I wouldnāt be able to tell in that example, either. movwin works around that by (mostly) assuming that there is no support for colors at all, so there should always be a way to tell which widget has focus, even without colors. Thatās why it puts brackets around a buttonās label when focused:
The fewer colors you use, the better, I guess. š¤
tt. But then, in the message tree, I spot another missed typo. My process is then to go to my twtxt.txt and fix it by hand. However, I still have to clean up tt's cache. This is rather tidious:
Now Iām curious how movwin deals with that. ;-)
Focus handling? I hardly remember, lol. š Did that 6 months ago and havenāt touched it since. Letās see.
The core main loop gets keyboard/mouse events from curses. At this level, the main loop only knows about exactly one widget, so it passes the event to that widget (whatever that is, doesnāt matter ā they all inherit from the Widget base class, it could be a Window, a WindowManager, or an Edit box directly).
The outermost widget is usually a WindowManager. It implements a few hotkeys of its own, like switching to another window. If none of those hotkeys match, it passes the event to the currently focused window.
Same story here: Window implements some hotkeys (like opening the menu bar). If none of those match, then ⦠the magic happens.
Each Window acts as a focus manager. It can descend into its child widget hierarchy and collect all child widgets in a depth-first search. They are collected into a flat list. Each Window then has an attribute _focus_position, which is an index into that list. Pressing Tab or Shift+Tab increases or decreases that index and that allows you to select the next/previous focusable widget in the current window.
Eventually, Window passes the input event to the currently focused widget.
Usually on initialization, the application can ask a Window object to focus a certain widget. The file selection dialog does that, for example, because the ānaturalā focus order would be to focus the Edit box at the top of the window first ā but thatās not what the user wants, the Table showing the list of files should be focused.
If no widget ever feels responsible for handling a certain input event, then thereās a global unhandled_input callback that the application can provide (same as in urwid).
I think thatās it.
Hm, thatās more complicated than I remembered, but apparently it works fine, because I completely forgot about this. š
All I did in the last few months was make new classes that inherit from Widget, like the new Table class or Edit or HexEdit or whatever, and if they want to get input events, then they must implement the methods input_key() or input_mouse().
Does this answer your question? š (I admit that I didnāt exactly understand your scenario, so I just went ahead and rambled about my implementation. š )
@movq@www.uninformativ.de Oh yeah, way better! :-) I didnāt spot the bug, though.
I think I could work with the feature set. I typically donāt need a lot. Until I do. :-D The message tree in tt is an example of that. But tt is also special that it needs something like this in the first place. Itās unusual.
@itsericwoodward@itsericwoodward.com on this one, for example.
@lyse@lyse.isobeef.org Ah, I almost thought so (that you wrote it by hand), but then I looked at the source code and saw the TOC and I was like: āNaah, probably not. I would be way too lazy to do that manually.ā š And indeed ⦠ha.
Oh god, yeah, thatās a lot of <span>. š¤ Canāt really avoid that, I guess, especially if you want to do syntax highlighting of code blocks.
You wrote your own site generator, didnāt you?
In parts. I write everything in Markdown (itās online, even: https://movq.de/blog/postings/2026-05-29/0/POSTING-en.md), plus a few Vim shortcuts (to generate thumbnails, for example), and then python-markdown renders it: https://pypi.org/project/Markdown/ This process is wrapped in a shell script, like āre-render every page if the .md file is newer than the .html fileā and thatās mostly it. And the Atom feed generator is completely custom. š¤
LIke with almost everything ābig-techā has done, itās not the tech you should not trust, but the companies themselves. For example, accessing and using the models (because letās face it, they have clusters of much larger and more powerful GPU clusters than we could ever afford to build and own ourselves, at least for now) is fine, but trusting their end-user products/services, not so much.
@prologic@twtxt.net Ahh, I see. Okay, Iām with you there. On this high level, I can understand how the thing works.
Maybe my wording isnāt good. š¤ Letās take a real life example from what we do at work.
Thereās this AI chatbot. It gets support requests from users, so the user says something like āI need access to a particular systemā. This triggers the bot to ārunā the instructions stored in a large Markdown file, like ācheck if the user is authorized to do this, then issue the following API requestsā, and so on. This is essentially like running a little script, except itās written in natural language (German) and thereās no āscript interpreterā but just the AI.
Now, suppose that the AI doesnāt quite do what was intended. Thereās some subtle bug. How do you debug this? How do you find out how the AI came to the āconclusionā to run step A instead of step B? And how do you find out how exactly you have to change your prompt so this doesnāt happen again next time?
If this was an actual script/program instead of AI, you could repeat the request and attach a debugger or throw in some printf() or whatever. How do you do that kind of thing with AI? How do you pinpoint exactly what the problem was?
(Or is this just a stupid idea? Do we have to give up that way of thinking when using AI? Is the era of debuggability over?)
So going back to the understanding of how it generated this, is quite simply the most statistically relevant search space of itās weights it has been trianed on and it has basically just produced a series of tokens, one after another that are relevant to the input, the next token and so on. Itās a trivial example I know, but it basically pattern matches itās way through itās vast search space just producing outputs based on context.
@movq@www.uninformativ.de I think your points are pretty clear to me, thatās fine. Iām just seeing if you can perhaps see things a different way maybe?š¤ I would challenge the assertion that you cannot understand how Claude Code generated an output; which I can demonstrate easily with a fairly trivial example by the input:
Write a program in Go that sums a list of numbers from stdin and prints the result.
Most of the time, I take a very very long time to do anything. If I say, for example, āIāll build an IRC Web Clientā, that may not happen for weeks, if not months, until my sub conscience has has time to process everything. Itās like basically a āfeelingā of internal readiness. I never talk through it, never actively think about it, it just happens.
@bender@twtxt.net Fine, Let me answer properly and concretely š
Would you want your children not to learn anything, because āthey have AIā?
No, children still need to learn. That will never change. What they learn however will over time.
Are you OK with your children using the AI for all of their homework?
Yes, frankly I am. Why? Because much of what we teach them in school is utterly pointless.
For example, learning to read Shakespear never taught me anything useful in my life. I regret much of my school years to be honest.
I leanred to read and write, sure. But I learned Math, Science, Computing and how things work on my own by being very curious.
What sense will it make?
That assumes I answered ānoā, which I did not. So it all makes perfect sense :D
What kind of future would that bring for them?
This assumes I said āYesā, which I did :D It will be an itneresting future thatās for sure. I donāt think we can just bury our heads in teh sand and pretend itās all going to go away, It will not. It will make things very interesting for sure, as weāre already starting to see whatās possible and whatās changeing. For example; ordinary people are using these LLM(s) to write their legal suit and defense in courts with varying levels of success.
Even if AI were to become omniscient, what will it be of the human race then?
Iām not convinced it ever will. In fact, I am not convinced we know how to create true intellience at all.
What would we do?
What would be so different from say an Alien invasion from far superious beings?
What would we do that? Band together and defend humanity?
Serve the AI? Maintain the AI?
That assumes that āAIā will become intelligent and omniscient, which I donāt believe it ever will.
Would we have found the true meaning of life then?
If the meaning of life is to create our own sub-species liken to ourselves, sure, maybe. But is that even a reality? not sure, I doubt it. We barely understand ourselves at the best of times, let alone how our minds works.
To care for AI, Is that it?
How would this be different to caring for a friend, a family member If we could ever truly reate an actual sentient being with real feelings and intelligenace, is there any reason to worry? Could we not be freinds and have mutual goals and form relationships?
@prologic@twtxt.net I donāt believe you. For example, you are programming something, and you are planning the steps, or you struggle at certain point. Any train of thought, of any kind, has an addressing. āIf I move this here, what will it happen?ā. āHmm if weāre to place this logic here, will it do what we need?ā. āIf I were to do this, will it work?ā āDamn it, you are so stupid, James, how could you miss that?!!ā And so on. š And thatās just a minor thing.
Trust me, you do. We all do. Even the crazy ones.
@tftp@tilde.town mentioning in here requires he whole shebang. With jenny, if using vim, there is a key combination:
Nick name completions: Allows you to use ^X ^U to turn verbatim nick names into full twtxt mentions. For example, typing ācathā and then pressing ^X ^U will turn ācathā into a full mention, like ā@ā. (This function will read the contents of your ā~/.config/jenny/followā file.)
Iām pleased to announce that express-twtkpr (my ExpressJS library for hosting, editing, and posting to a twtxt.txt file) continues to crawl towards a full release with another (pre-alpha) update published to NPM. This update includes a whole new plugin system, and even a (little) more documentation. Check it out, if you dare (and use it at your own risk): https://www.npmjs.com/package/express-twtkpr
And speaking of plugins, hereās where the funās at: announcing express-twtkpr-core-plugins, a set of 3 plugins for your TwtKpr install: emojiButton, uploadButton, and postToMastodon. Like express-twtkpr, this set of plugins is still in pre-alpha, and lacks documentation, examples, tests, installation flexibility, or polish (so also use them at your own risk). Other than that, they work great: https://www.npmjs.com/package/express-twtkpr-core-plugins



Stay tuned for more! š¤
All sorts of .de domains donāt resolve right now. But not all, movq.de for example still works. All on our server and basically all major other sites are cactus. Maybe some DENIC problem? Iām too tired to investigate, but Iām looking forward to tomorrow to read some report on that. :-) Good night.
@lyse@lyse.isobeef.org Thank you for the suggestions. I will probably do some of that when I have time. For the thumbnails, Iām also thinking about trying the loading=ālazyā img attribute. Top on my mind is actually understanding why the big images donāt load. Maybe my VPSās network connection is saturated, for example. Iāve never needed to worry about such things until now. Iām looking forward to spending some time on it.
express-twtkpr: an ExpressJS library that enables hosting (and directly posting to) a twtxt.txt file. It works great (otherwise you wouldn't be able to read this), but it's still in alpha and lacks documentation, examples, tests, installation flexibility, or polish, so please use it at your own risk. Enjoy! https://www.npmjs.com/package/express-twtkpr
@bender@twtxt.net Thanks for the tip-off, fixed!
I hope to have some time this weekend to tease apart my current setup and build a couple of example sites with it (while also writing some docs along the way). But given the rate Iāve been going, itāll probably be another month. š¢
Iām happy to report that, earlier today, I published an early version of express-twtkpr: an ExpressJS library that enables hosting (and directly posting to) a twtxt.txt file. It works great (otherwise you wouldnāt be able to read this), but itās still in alpha and lacks documentation, examples, tests, installation flexibility, or polish, so please use it at your own risk. Enjoy! https://www.npmjs.com/package/express-twtkpr
@rdlmda@rdlmda.me I am reasonably happy with jenny. If I find time for a twtxt project, I would like to make a web page that works as follows: you point it to your own twtxt feed (as a URL parameter), and then it shows you all the feeds referenced by your ā# follow =ā lines. So, if I put this up, anyone could use it to view their own feed, with no login required. (Probably a difficult project. For example, Iād want to make sure the backend couldnāt be tricked into helping ddos a web server by trying to fetch lots of āfeedsā from it. Anyway, I have too many other projects.)
@rdlmda@rdlmda.me youāve got to get a nice client. For example, that mention is broken.
@movq@www.uninformativ.de I noticed that your feedās last modification timestamp was missing in my database. I cannot tell for certain, but I think it did work before. Turns out, your httpd now sends the Last-Modified with UTC instead of GMT. Current example:
Sat, 03 Jan 2026 06:50:20 UTC
Iām not a fan of this timestamp format at all, but according to the HTTP specification, HTTP-date must always use GMT for a timezone, nothing else: https://httpwg.org/specs/rfc9110.html#http.date
@prologic@twtxt.net Anything by Charlotte de Witte. š For example:
https://www.youtube.com/watch?v=QfkgSlmoe1I
Seeing this run on real hardware is so satisfying, even if itās just a small example. š
@prologic@twtxt.net @movq@www.uninformativ.de Oh, I take my 0°C over the 36°C anytime! Even with yesterdayās gray and windy sleet in my face. However, there are definitely more pleasant times to walk in town, Iāll give you that. For example on 0°C sunny today: https://lyse.isobeef.org/waldspaziergang-2025-12-25/
Oh great, I received an e-mail that my SMTP credentials have been exposed. Once again, just another shitty scanner that generates garbage reports from tests it doesnāt understand. Thank you for nothing!
conf := &Config{
SMTPHost: "smtp.example.com",
SMTPPort: 587,
SMTPUser: "user",
SMTPPass: "hunter2",
SMTPFrom: "from@example.com",
}
Ahh thatās because I forgot to call main() at the end of the source file. mu is a bit of a dynamic programming language, mix of Go(ish) and Python(ish).
$ ./bin/mu examples/aoc2025/day1.mu
Execution failed: undefined variable readline
Come back from my trip, run my AoC 2025 Day 1 solution in my own language (mu) and find it didnāt run correctly 𤣠Ooops!
$ ./bin/mu examples/aoc2025/day1.mu
closure[0x140001544e0]
@movq@www.uninformativ.de Same. :ā-( I just donāt get how people do code archeology with all their shit messages and huge commits changing a gazillion of different things. I always try to lead by setting good examples, but nofuckingbody is picking up on that. At all. Even when bringing this up every now and then.
This is an example of the kind of garbage release notes from this conventional commit autogenerated crap š¤£

@bender@twtxt.net actually I think itās a little more nuance than that because for example with salty chat, we have support for DNS based delegation via SRV records and your identity is associated with your Apex Dom name and of course the keys.
I actually donāt understand why Federation and activity pub is so goddamn hard to migrate from one instance to another š§
Gootosocial to a Pleroma one. While GTS is kinda cute (lightweight and easy to manage) of a software, the inability to fetch/scroll through people's past toots when visiting a profile or having access to a federated timeline and a proper search functionality ...etc felt like handicap for the past N months.
@bender@twtxt.net yeah, Iāve been reading through the documentation last night and it felt overwhelming for a minute⦠+1 point goes to GTSās docs. but hey, Iāll be taking the easy route: podman-compose up -d they provide both a container image and an example compose file in a separate git repo but Iām wondering why that is not mentioned anywhere in the docs, (unless it is and I havenāt seen it yet)
@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. šš )
Iām kind of tired of late of telling support folks, for example, ym registrar, how to do their fucking goddamn jobs š¤¦āāļø
Hi James,
Thank you for your patience.
There are several reasons why a .au domain registration might fail or be cancelled, including inaccurate registrant information, ineligibility for a .au domain licence, or issues related to Australian law.
For a full list of possible reasons, please see this article: https://support.onlydomains.com/hc/en-gb/articles/6415278890141-Why-has-my-au-domain-registration-been-cancelled
If you believe none of these reasons apply to your case, please let us know so we can investigate further.
Best regards,
Yes, so tell me support person, why the fuck did it fail?! š¤¬
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/
@prologic@twtxt.net I prefer something like the logo on https://twtxt.dev, for example, instead. But hey, it is your pod, have fun!
FTR, I see one (two) issues with PyQt6, sadly:
- The PyQt6 docs appear to be mostly auto-generated from the C++ docs. And they contain many errors or broken examples (due to the auto-conversion). I found this relatively unpleasent to work with.
- (Until Python finally gets rid of the Global Interpreter Lock properly, itās not really suited for GUI programs anyway ā in my opinion. You canāt offload anything to a second thread, because the whole program is still single-threaded. This would have made my fractal rendering program impossible, for example.)
@bender@twtxt.net to work through both https and gemini, the site is not written in HTML, but in Gemtext, automatically converted to HTML, when needed. Gemtext is nicely explained for example here: https://garden.bouncepaw.com/hypha/gemtext . In short, it is so limited, no line can be more than one thing, so no links in a list are possible, othar than doing it through something like this primitive workaround.
@prologic@twtxt.net Letās go through it one by one. Hereās a wall of text that took me over 1.5 hours to write.
The criticism of AI as untrustworthy is a problem of misapplication, not capability.This section says AI should not be treated as an authority. This is actually just what I said, except the AI phrased/framed it like it was a counter-argument.
The AI also said that users must develop āAI literacyā, again phrasing/framing it like a counter-argument. Well, that is also just what I said. I said you should treat AI output like a random blog and you should verify the sources, yadda yadda. That is āAI literacyā, isnāt it?
My text went one step further, though: I said that when you take this requirement of āAI literacyā into account, you basically end up with a fancy search engine, with extra overhead that costs time. The AI missed/ignored this in its reply.
Okay, so, the AI also said that you should use AI tools just for drafting and brainstorming. Granted, a very rough draft of something will probably be doable. But then you have to diligently verify every little detail of this draft ā okay, fine, a draft is a draft, itās fine if it contains errors. The thing is, though, that you really must do this verification. And I claim that many people will not do it, because AI outputs look sooooo convincing, they donāt feel like a draft that needs editing.
Can you, as an expert, still use an AI draft as a basis/foundation? Yeah, probably. But hereās the kicker: You did not create that draft. You were not involved in the āthought processā behind it. When you, a human being, make a draft, you often think something like: āOkay, I want to draw a picture of a landscape and thereās going to be a little house, but for now, Iāll just put in a rough sketch of the house and add the details later.ā You are aware of what you left out. When the AI did the draft, you are not aware of whatās missing ā even more so when every AI output already looks like a final product. For me, personally, this makes it much harder and slower to verify such a draft, and I mentioned this in my text.
Skill Erosion vs. Skill EvolutionYou, @prologic@twtxt.net, also mentioned this in your car tyre example.
In my text, I gave two analogies: The gym analogy and the Google Translate analogy. Your car tyre example falls in the same category, but Geminiās calculator example is different (and, again, gaslight-y, see below).
What I meant in my text: A person wants to be a programmer. To me, a programmer is a person who writes code, understands code, maintains code, writes documentation, and so on. In your example, a person who changes a car tyre would be a mechanic. Now, if you use AI to write the code and documentation for you, are you still a programmer? If you have no understanding of said code, are you a programmer? A person who does not know how to change a car tyre, is that still a mechanic?
No, youāre something else. You should not be hired as a programmer or a mechanic.
Yes, that is āskill evolutionā ā which is pretty much my point! But the AI framed it like a counter-argument. It didnāt understand my text.
(But what if thatās our future? What if all programming will look like that in some years? I claim: Itās not possible. If you donāt know how to program, then you donāt know how to read/understand code written by an AI. You are something else, but youāre not a programmer. It might be valid to be something else ā but that wasnāt my point, my point was that youāre not a bloody programmer.)
Geminiās calculator example is garbage, I think. Crunching numbers and doing mathematics (i.e., ācomplex problem-solvingā) are two different things. Just because you now have a calculator, doesnāt mean itāll free you up to do mathematical proofs or whatever.
What would have worked is this: Letās say youāre an accountant and you sum up spendings. Without a calculator, this takes a lot of time and is error prone. But when you have one, you can work faster. But once again, thereās a little gaslight-y detail: A calculator is correct. Yes, it could have ābugsā (hello Intel FDIV), but its design actually properly calculates numbers. AI, on the other hand, does not understand a thing (our current AI, that is), itās just a statistical model. So, this modified example (āaccountant with a calculatorā) would actually have to be phrased like this: Suppose thereās an accountant and you give her a magic box that spits out the correct result in, what, I donāt know, 70-90% of the time. The accountant couldnāt rely on this box now, could she? Sheād either have to double-check everything or accept possibly wrong results. And that is how I feel like when I work with AI tools.
Gemini has no idea that its calculator example doesnāt make sense. It just spits out some generic āargumentā that it picked up on some website.
3. The Technical and Legal Perspective (Scraping and Copyright)The AI makes two points here. The first one, I might actually agree with (ābad bot behavior is not the fault of AI itselfā).
The second point is, once again, gaslighting, because it is phrased/framed like a counter-argument. It implies that I said something which I didnāt. Like the AI, I said that you would have to adjust the copyright law! At the same time, the AI answer didnāt even question whether itās okay to break the current law or not. It just said ālol yeah, change the lawsā. (I wonder in what way the laws would have to be changed in the AIās āopinionā, because some of these changes could kill some business opportunities ā or the laws would have to have special AI clauses that only benefit the AI techbros. But I digress, that wasnāt part of Geminiās answer.)
tl;drExcept for one point, I donāt accept any of Geminiās ācriticismā. It didnāt pick up on lots of details, ignored arguments, and I can just instinctively tell that this thing does not understand anything it wrote (which is correct, itās just a statistical model).
And it framed everything like a counter-argument, while actually repeating what I said. Thatās gaslighting: When Alice says āthe sky is blueā and Bob replies with āwhy do you say the sky is purple?!ā
But it sure looks convincing, doesnāt it?
Never againThis took so much of my time. I wonāt do this again. š
You do raise very good points though, but I donāt think any of this is particularly new because there are many other examples of technology and evolution of change over time where people have forgotten certain skills like for example, changing a car tyre
Javaās Swing is allegedly in āmaintenance modeā, so I doubt itās a good idea to use it for new programs. For example, I very much doubt that it will ever support Wayland.
The replacement is supposed to be JavaFX, but thatās not included in JREs ā anymore! It used to be, now itās not, even though itās well over 15 years old now.
This whole thing (āJava GUIsā) appears to have stagnated a lot. Probably because everything is web stuff these days ā¦
https://www.oracle.com/java/technologies/javafx/faq-javafx.html#6
@bender@twtxt.net I guess most clocks donāt support that. š My wrist watch can do it, you can select it in the menu:

In general, different transmitter means different frequency and different encoding, for example these two:

