Making the agents learn

Making the agents learn

As you might have noticed, I have been working on plenty of projects lately.
First the Desktop framework comparison, followed by experimenting with Qt and Rust and then the switch back to Flutter, including a bunch of applications that I was missing for Linux and macOS in the quality I wanted them to be.

All those projects follow the same pattern. Depending on the programming language, I have a set of utilities, a common architecture and a defined way of implementing the applications.
Initially, I did it by just telling the agent: “Here is this other project, please take the architecture, DI system, logging, error handling, translation system and everything that is generic and apply it here” as one of the first steps.
This worked quite well as long as there were 2 or maybe 3 projects. The shared knowledge only lived in the source code and markdown files of specific projects.
On top of that, I noticed that there are classes of errors that the agents make all over again, ranging from simple UI glitches like a wrong animation in custom context menus to more complex issues around multi-window handling.
Those issues started to pile up and I was in desperate need of a shared “agent knowledge” system.

Looking for “off the shelf” solutions

I started to look for a solution that works “out of the box”, but the ones I found were either way too complex for my setup or lacking one basic requirement that I had.
I thought about how a knowledge system can work, be reliable and stay up to date. My biggest concern was agents just dropping knowledge bits from their context into the knowledge system, which would ultimately bloat it and finally make it unusable.
So I was looking for a system that separates the knowledge “finding” from maintaining the knowledge system.
After some back and forth and a couple of evenings discussing with my agent, I came up with a solution that works quite well for me, so I want to share it here.

The knowledge system

The system is quite straightforward. I called it “Foundry” and it lives in its own Git repository, so Git is basically the memory of the system. The knowledge is a structure of markdown files that link to each other. It contains small knowledge bits (e.g. “When you encounter this kind of crash, then here is what the solution has been for other projects”) and bigger things like a “Flutter profile” that contains the mentioned blueprint for how Devmil Flutter projects are structured.
Every agent gets a small hook for the knowledge system that explains how to retrieve information and how to propose additions or changes.
The entry point is an index that only routes to small, focused documents. This way an agent only loads what it actually needs for the task at hand instead of the whole knowledge base.
If an agent comes to the conclusion that whatever knowledge it built might be valuable for other agents or projects as well, it can propose a change to the knowledge system. This is basically a branch that contains a markdown file with a defined structure and content. And that’s it.
To prevent the bloat I was afraid of, an agent is only allowed to propose something if the problem showed up in more than one project or task, if the failure was costly enough to justify a check, or if existing knowledge turned out to be wrong or outdated. Product-specific behavior, personal preferences and workarounds where nobody knows why they work are not welcome.
Here is a real (shortened) example from one of my Flutter apps:

# A post-frame callback does not request a frame

- Scope: `flutter`
- Source: GitLama command-line remote open
- Verification status: `complete`

## Summary
WidgetsBinding.addPostFrameCallback only queues work for the next frame;
it does not schedule one. An effect deferred that way from a stream event,
IPC message or timer in an idle window waits until something else repaints,
possibly never. [...]

## Evidence
A command forwarded from the command line reached HomeScreen through a
broadcast stream. [...] A widget test pumping 12 frames never ran the callback. [...]

## Recommended Foundry change
Extend profiles/flutter/navigation-effects.md [...]

## Validation
The widget test failed with the post-frame deferral and passes with direct dispatch. [...]

Another agent then goes through the proposals and decides if this is a valid change / addition, and if it is, it also decides where in the knowledge system this bit needs to be placed. While doing this, the knowledge maintainer agent can also rearrange things and restructure the index if necessary.
A review is final: a proposal is either accepted or rejected, there is no back and forth with the agent that proposed it. If a proposal isn’t solid yet, it gets rejected and a later session can propose it again with better evidence. And I still have the final say: nothing gets merged without my OK.
To make sure that the system works and to see if there is some optimization potential, I added an observability layer that tracks those agent sessions and records how many pages of the knowledge system were loaded and how many of them were actually helpful, while also tracking a rough estimation of tokens used per context. This way I can see if the knowledge system is actually helping the agents to be more efficient and if it is worth the effort to maintain it.

Read more...

Software developmentai

Some (Desktop) software development updates

Some (Desktop) software development updates

The Qt path

As mentioned in the previous post, I wanted to give Qt a try to see if it handles the HTML problem better, than Flutter.
It took quite some effort to reach the UI polish that the Flutter version had but I eventually got there. Almost at least 😃.
The result was a bit mixed. While it solved the webview issue way better than Flutter, the approach that Qt takes also has some drawbacks:

  1. The complete web engine gets bundled with the app (the engine and the Qt specific additions and integrations). Which is OK in this day and age but still I consider that a downside. To get a better idea: on macOS the installed application has around 450MB. The Flutter version has around 230MB.
  2. Performance: While the webview at least works on Linux its performance on macOS was way worse than in the Flutter version. I didn’t measure concrete timings but it takes longer to load the web content.

I also continued to experiment with the rendering performance on Linux with both - Flutter and Qt - and in the end both of them have a problem getting resized smoothly on Linux. After fine-tuning there is no visible difference any more between Qt and Flutter. Both are bad 😃.

Read more...

Software developmentRustFlutter

Another Desktop tech stack enters the scene

Another desktop tech stack enters the scene

As mentioned in my last blog post, I’m currently experimenting with different tech stacks on the desktop.
That last post compared Swift + Rust, KMP + Rust and Flutter + Rust running on a Mac.

The result of this experiment was that the Flutter + Rust combination did quite a good job in terms of RAM and CPU usage while having some downsides on the bundle size side.

In addition to the Process Explorer I’m currently working on a bunch of other desktop applications.
One of those is a Proton mail client. Proton internally is already working on native clients but currently Proton’s official desktop client wraps its web application in Electron. It works, but I am not happy with its performance, memory use, or integration with the operating system.

I got so annoyed that I decided to build my own. Proton has open-sourced its clients, and its newer mobile architecture puts shared application logic in a Rust SDK with native UIs on top.
The official iOS and Android clients already use this approach. Native desktop clients appear to be in development as well.

Using that shared Rust library as a base made it really “easy” for me and my AI to build a Flutter application on top of it.
I don’t plan to release that one but I use it as a daily driver and it works and looks really nice.

CrossProton Screenshot

Then Linux happened

I’m currently (again) in a “I’ll give Linux another shot” phase. My thinking: For all the tools that are missing I create a version myself. Easy! 😁

Read more...

Software developmentRust

Desktop framework comparison

Desktop framework comparison

Background

As mentioned in the previous post, I have been working on a process explorer for macOS (Yggdrasil).
I wanted to know how Swift + Rust compares to other frameworks, especially cross platform frameworks, so I decided to build variants of the process explorer in Flutter + Rust and in Kotlin Multiplatform (KMP) + Rust.

To stay in the nordic naming scheme, I decided to give them all nordic names around the Yggdrasil tree which leads us to:

Framework Name Status
Yggdrasil Logo Swift + Rust Yggdrasil Released
Mimameidr Logo Flutter + Rust Mimameidr Released (Beta)
Glasir Logo Kotlin Multiplatform + Rust Glasir In progress

They all share the same Rust library to actually access the process information but differ slightly in the UI and features.
Yggdrasil has the most advanced feature set as it includes a dedicated helper to access more information of system processes and also provides a document preview for exported snapshots. This was just me trying to do as many macOS specific things as possible 🤣.
Mimameidr is a close second. It lacks the helper and the document preview but other than that it is very similar in terms of feature set. It even has some more advanced ways of showing the graphs (you can switch between tree and process only).
Glasir is in the middle of development and I’m not sure if I will put as much work and love into that one as I did into the other two. More on that later.

Read more...

Software developmentFlutter

New applications

New applications

In the last few months, I have been working on a bunch of new applications.
Feeling the itch to use all the AI credits I had available and to squeeze out the budget before it reset, I spent almost all of my spare time in April and May working on new projects or project ideas that had been lingering in my head for a while.

Now, in June, I decided to take a step back and slow things down for a bit after my wife complained that I was in my office non-stop. First home office, a short family time during dinner, putting our youngest kid to bed, and then back into the office to work on projects until late at night.

Anyway, that phase was very productive. Now I have one game in the stores, one game stuck at ~70%, another promising game at 80%, and a new process explorer.

I used these projects to experiment with different AI providers, compare their outputs, and analyze the strengths and weaknesses of each to get a better understanding of the current state of AI and how to best use it in different situations (also at work).

One goal was to provide the infrastructure for the applications, define guardrails and basic rules for the AI, and then try to let the AI do as much of the work as possible. I still reviewed the code at a high level (architectural violations and such) and did the commits / PRs manually.

This worked quite well. I took the infrastructure bits from Mirroly (custom DI solution, logging approach, architecture, and abstraction levels), and the first task for the AI was to copy that code and adapt it to the new project.
I think the result was pretty good and helped a lot to get the project up and running quickly.

I feel like this approach also made it really easy for me to detect when the AI was taking a suspicious turn, as just looking at the code areas touched was already a super strong signal. I could then review the code and give feedback to steer it back on track. Basically, I treated the AI as a junior developer and tried to provide guardrails through the code architecture and basic design rules.

But now let me briefly talk about the released projects:

VØID Arc

Read more...

Software developmentFlutter

Why most applications should be cross-platform

Why most applications should be cross-platform

I know this is a hot take, and not everyone will agree. Some of you may even “strongly disagree” 😅.

Still, I want to make the case that most applications should be cross-platform - and that users should care about this too.

I’m biased and I admit it

First, I should be honest: I’m biased.

In two major ways:

  1. I’m a Flutter developer. Of course I think that Flutter (or cross-platform development in general) is the right way to go for most applications.
  2. I tend to switch platforms regularly. Android and iOS, macOS and Linux mostly and I hate it when I cannot use an application that I like on my target platform.

So yes, I have strong feelings from both a developer and user perspective.

Read more...

Software developmentFlutter

Monitor Supercharge

Monitor Supercharge

You know, I’m a hardware geek and perfectionist. This is a very bad combination.
This already led me into buying plenty of Android phones because there was always something that annoyed me and I knew there was something out there that would do a better job in this particular aspect.

I think I have it under control much better now than in the past but it still hits me and my monitor story is a proof of this 😏.

What happened so far

As described here: Monitor progression I ended up using an Apple Studio Display and was quite happy with it.

Then came my switch back to Android and things weren’t as gold as inside the cage any more so I switched to a Samsung Viewfinity 5k monitor (see Testing old new waters with Linux).

This was also working quite nicely until I tried some gaming on my ThinkPad. The poor Intel IRIS graphics card was hopelessly overwhelmed by the 5k display and one could feel that it was not meant to drive that amount of pixels.

At work we have plenty of 4k displays (most of them from LG) and running macOS on them works quite well. My eyes are bad enough to not distinguish 5k from 4k to be honest 🙈.
BetterDisplay did the rest to enable HiDPI scaling on those monitors so everything was fine.

So I decided to go with one of the lower end LG 4k displays (LG Ultrafine 27US550 to be exact).

LG Ultrafine 27US550

This worked OK in my setup and I was a happy man… at least for some time.
Looking at the MacBook Pro screen next to the LG didn’t do the LG monitor a favour…

Read more...

PersonalDev Setup

The return of the Mac

The Return of the Mac

Maybe you remember my last post about my journey from a MacBook to a ThinkPad running Fedora …well, it’s over 😀

I really wanted this to work. I have put a crazy amount of effort into configuring my new beloved system exactly the way I wanted it.
I was proud to have this thing that I own completely. New OS distro to try out? No problem: swap out the SSD and run it. Don’t like it? Just install the old SSD again.
Also all the features that KDE comes with are simply crazy. If you imagine that this is being done by hundreds of people who just do that for the fun of it, or because they see some purpose in doing that. Crazy.
All the things that “just work”. I never expected that given my Linux experience from a decade ago.

What Worked

Most of the Things I Do on a Daily Basis Actually Work. at least, Kind Of:

  • Browsing the web ✔
  • Building Flutter apps ✔
    • Even for iOS (kind of - performance is really bad) ✔
  • bash, Warp, Bitwarden, Affine, Seafile, Thunderbird, Vivaldi, VS Code, Antigravity, Android Studio - all work ✔
  • Having Gemini in a Chrome App ✔
  • Sending files with LocalSend ✔
  • native Wireguard integration in KDE ✔
  • having stats like network activity, CPU activity, … in the status bar ✔

Some Things Did Not Work but Were Solvable

  • Having a Resilio Sync status bar symbol (vibe coded one) ✔
  • Native GeForce Now app -> Chrome App (more on that later) ✔
  • A good Git GUI (used Fork on a Mac, which is - hands down - the best Git GUI) -> switched to GitKraken. Not really fast and a bit weird, but does its job ✔
  • Screenshot tool was really not that good. I use CleanShotX on my Mac, and there is nothing that even remotely comes close. I was about to vibe code my own (✔)

What Did Not Work

  • MoneyMoney. I tried several Linux alternatives. But that’s just a pile of garbage, to be honest. There was that one application that kinda worked but it looked like a Java application from 2000 (maybe because it was 🤷‍♂️😂)
  • Wiso Steuer. The tax software I use. There is no way that I would use a web based tax declaration service. I would rather install Windows into a virtual machine, and do my tax declaration in there.
Read more...

Software developmentPersonalDev Setup

An interesting ThinkPad twist

An interesting ThinkPad twist

My Lenovo ThinkPad T14s story got an interesting twist that I never experienced before that led to me owning a Lenovo ThinkPad T14 now.

The original plan

I decided to setup a Windows partition on my ThinkPad in order to make use of my eGPU and play some games. Mainly Cyberpunk 2077 and Diablo 4.

I tried to run the games on Linux using Steam and Bottles which worked but especially Cyberpunk was a bit unstable.

The Unexpected Discovery

So I installed Windows on a dedicated partition and in the initial setup screen of Windows I was greeted with the Microsoft login dialog that weirdly showed the logo of a small German company and the proposal in the E-Mail field also ended with the domain of that bespoke company.

I’m not too familiar with the different enterprise setup options of Windows but I suspected that this notebook still was part of some enterprise program.

The plot Twist

So I contacted the seller and asked what the problem could be. He replied and said he most probably forgot to remove this device in the company’s management software and told me to do this the next day.

Read more...

Software developmentPersonalDev Setup

Testing old new waters with Linux

Testing old new waters with Linux

I was using a MacBook as main device at home since ~2019 and at work since ~2022.

For me MacBooks are a near perfect combination of robustness, ease of use and flexibility.
With the Apple Silicon transition Apple added performance, no fan noise and battery life to that already long list.

The macOS software ecosystem is full of really nice apps. From home banking (MoneyMoney) over system stats (iStatMenus) to awesome Git clients (Fork). All are perfectly tailored to the very limited set of variation that can happen in Apple land.

Then I decided to go all-in: Apple keyboard, iPhone, Apple Watch, iPad and even an Apple Studio Display and I was happily living the Apple dream 😀 (I left out the Apple Mouse. Sorry but everyone needs to have a line that is not crossed 😉)

Last year a few things happened: I got bored, Apple decided to use some really dubious arguments to get itself out of some EU regulations and promised AI things that were not even remotely finished (as it turned out lately they seem to have been caught off guard on that end) so I decided to go back to Android again.

To be honest: It felt wrong in iOS land for me the whole time. I’m an Android developer at heart and I think this won’t change that easily. It feels right to carry a device around that can contain the apps that I love most developing. Maybe weird but I’m sure there are some people out there that can understand me.

Replacing my iPad with a Samsung Tablet made the Apple Studio Display useless for the “tablet connected to monitor” use-case. Not that I do that very frequently but just knowing that this is not an option drove me nuts so I sold the Studio Display and went with the Samsung Viewfinity S9.

So at that point I was already half way out of the Apple ecosystem.

Since the beginning of this year I frequently ran into capacity issues on my M1 MacBook (512 GB) so I was seeking a replacement with more storage (and RAM, I had 16GB).
I quickly configured a M4 MacBook and immediately discarded that idea seeing the price. I don’t have CPU performance issues, I just wanted to increase memory and storage so I also had a look at used MacBooks that meet my requirements.
At that point I realized that it would cost me around 1600€ to do that upgrade.

Read more...

Software developmentPersonalDev SetupFlutter