Search Results: "zed"

6 August 2026

Bits from Debian: DebConf26 closes in Santa Fe and DebConf27 announced

DebConf26 group photo - click to enlarge On Saturday 25 July 2026, the annual Debian Developers and Contributors Conference came to a close. Over 270 attendees representing 35 countries from around the world came together for a combined 90 events (including some which took place during the DebCamp) including more than 27 Talks, 21 Short Talks, 29 Birds of a Feather sessions ("BoF" informal meeting between developers and users), 8 workshops, and activities in support of furthering our distribution and free software, learning from our mentors and peers, building our community, and having a bit of fun. The conference was preceded by the annual DebCamp hacking session held 13 through 19 July where Debian Developers and Contributors convened to focus on their individual Debian-related projects or work in team sprints geared toward in-person collaboration in developing Debian. As has been the case for several years, a special effort has been made to welcome newcomers and help them become familiar with Debian and DebConf by organizing a sprint "New Contributors Onboarding" every day of Debcamp, followed more informally by mentorship during DebConf. Half a dozen new contributors joined the sessions and learned about Debian, free software, packaging and much more. This year, a week-long DebCamp session was dedicated to auditing, patching, and modernizing the Go ecosystem in Debian and enable the transition triggered by the recent upload of dh-golang enabling GO111MODULE=on by default in Experimental. In order to make the conference more accessible for local participants, a local language track was included in the schedule for talks in Spanish, as was done at DebConf19 in Brazil. The actual Debian Developers Conference started on Monday 20 July 2026. In addition to the traditional "Bits from the DPL" talk, the continuous key-signing party, lightning talks, and the announcement of next year's DebConf27, there were several update sessions shared by internal projects and teams. Many of the hosted discussion sessions were presented by our technical core teams with the usual and useful "Meet the Technical Committee", three talks about Linux Kernel, early boot and improving Debian s kernel and installer support for Chromebooks, and about twenty BoFs and talks about Debian packaging policy, Debian infrastructure, security and privacy. This year, and echoing ongoing discussions within the Free Software community, Artificial Intelligence and Age Verification have been the subject of several talks. The Python, Perl, Ruby, Go, and Rust programming language teams also shared updates on their work and efforts. More than 17 BoFs and talks about community, diversity, and local outreach highlighted the work of various teams involved in not just the technical but also the social aspect of our community The schedule was updated each day with planned and ad hoc activities introduced by attendees over the course of the conference. Several traditional activities took place: a poetry performance, the traditional Cheese and Wine party, the Group Photos, and the Day Trip. For those who were not able to attend, most of the talks and sessions were broadcasted live and recorded. One can find the seventy hours of recorded videos available via the conference schedule, or alternatively through this link. Almost all of the sessions facilitated remote participation via IRC and Matrix messaging apps or online collaborative text documents which allowed remote attendees to "be in the room" and ask questions or share comments with the speaker or assembled audience. DebConf26 saw over 341 T-shirts, a day trip, and up to 130 meals planned per day. All of these events, activities, conversations, and streams coupled with our love, interest, and participation in Debian and F/OSS certainly made this conference an overall success both here in Santa Fe, Argentina and online around the world. The DebConf26 website will remain active for archival purposes and will continue to offer links to the presentations and videos of talks and events. Next year, DebConf27 will be held in Asahikawa, Hokkaido, Japan, from Sunday September 5th to Saturday September 11th, 2027. As tradition follows before the next DebConf the local organizers in Japan will start the conference activities with DebCamp with a particular focus on individual and team work towards improving the distribution. DebConf is committed to a safe and welcome environment for all participants. See the web page about the Code of Conduct on the DebConf26 website for more details on this. Debian thanks the commitment of numerous sponsors to support DebConf26, particularly our Platinum Sponsors: Infomaniak, and Proxmox, and our Gold Sponsors : Freexian, and Viridien. We also wish to thank our Video and Infrastructure teams, the DebConf26 and DebConf committees, our host nation of Argentina, and each and every person who helped contribute to this event and to Debian overall. Thank you all for your work in helping Debian continue to be "The Universal Operating System". See you next year! About Debian The Debian Project was founded in 1993 by Ian Murdock to be a truly free community project. Since then the project has grown to be one of the largest and most influential Open Source projects. Thousands of volunteers from all over the world work together to create and maintain Debian software. Available in 70 languages, and supporting a huge range of computer types, Debian calls itself the universal operating system. About DebConf DebConf is the Debian Project's developer conference. In addition to a full schedule of technical, social and policy talks, DebConf provides an opportunity for developers, contributors and other interested people to meet in person and work together more closely. It has taken place annually since 2000 in locations as varied as Scotland, Bosnia and Herzegovina, India, Korea, France. More information about DebConf is available from https://debconf.org/. About Infomaniak Infomaniak is an independent, employee-owned Swiss technology company that designs, develops, and operates its own cloud infrastructure and digital services entirely in Switzerland. With over 300 employees more than 70% engineers and developers the company reinvests all profits into R&D. Its public cloud is built on OpenStack, with managed Kubernetes, Database as a Service, object storage, and sovereign AI services accessible via OpenAI-compatible APIs, all running on its own Swiss infrastructure. Infomaniak also develops a sovereign collaborative suite messaging, email, storage, online office tools, videoconferencing, and a built-in AI assistant developed in-house and as a privacy-respecting solution to proprietary platforms. Open source is central to how Infomaniak operates. Its latest data center (D4) runs on 100% renewable energy and uses no traditional cooling: all the heat generated by its servers is captured and fed into Geneva's district heating network, supplying up to 6,000 homes in winter and hot water year-round. The entire project has been documented and open-sourced at d4project.org. About Proxmox Proxmox develops powerful, yet easy-to-use open-source server solutions. The comprehensive open-source ecosystem is designed to manage divers IT landscapes, from single servers to large-scale distributed data centers. Our unified platform integrates server virtualization, easy backup, and rock-solid email security ensuring seamless interoperability across the entire portfolio. With the Proxmox Datacenter Manager, the ecosystem also offers a "single pane of glass" for centralized management across different locations. Since 2005, all Proxmox solutions have been built on the rock-solid Debian platform. We are proud to return to DebConf26 as a sponsor because the Debian community provides the foundation that makes our work possible. We believe in keeping IT simple, open, and under your control. Contact Information For further information, please visit the DebConf26 web page at https://debconf26.debconf.org/ or send mail to press@debian.org.

4 August 2026

Petter Reinholdtsen: FreeCAD MCP with llama.cpp, toy or tool?

After seeing a video a few months ago demonstrating how a proprietary CAM solution uses machine learning and large language models to automatically generate CNC instructions, and successfully testing it on a real CNC, I began wondering if the same could be achieved with free software. I still do not know the answer, but I may be getting closer to finding out. Two weeks ago, I came across the video "I Connected Claude AI to FreeCAD (And It Models Parts Like an Engineer)" by Make Form, which introduced me to the FreeCAD MCP project. Even though the video creator apparently believes it is acceptable to download and run random binaries from the Internet on a local machine (his setup uses UCX), I do not. I would probably have left the project alone entirely if I had not noticed that all of its dependencies are already available in Debian. This significantly boosted my motivation, so I set out to test it using packages built from source on Debian rather than relying on untrusted binaries. The first hurdle was that the MCP SDK for Python was not present on my Debian Forky test machine. I initially believed it was missing from Debian altogether, but it has been available in Debian Unstable for about a month and is only absent from Forky because some automated tests fail on architectures like riscv64 and s390. Fortunately, backporting it was straightforward using apt-get source -b python3-mcp . The next hurdle involved an outdated version of the Validators Python library. Since I am a member of Debian's Python team, which maintains this package, updating it to a sufficient version for FreeCAD MCP was relatively easy. I could not upgrade to the latest upstream release due to a new dependency on an Ethereum-related library, so I settled on a 2024 version. With those dependencies in place, I proceeded to create a Debian package for FreeCAD MCP. I had previously submitted a request for packaging of FreeCAD MCP to gauge interest while deciding whether to prioritize maintaining it myself. Because salsa.debian.org blocks access from Tor users like myself, I published my draft packaging scripts in a Git repository on Codeberg as the Debian FreeCAD MCP project and got it working with the FreeCAD 1.1 version in Forky. I initially struggled with the button controls for the MCP feature, which led me to submit a pull request titled "Fixed startup sync of checkable toolbar buttons" proposing a fix. Once this confusion was resolved and the MCP setup was enabled via the GUI, I was able to run FreeCAD completely headless using xvfb-run on a machine without an X server to generate models. I am using a private LLM service running the Debian package of llama.cpp with the Qwen 3.6 model downloaded from Hugging Face, configured with a maximum context window of 105k tokens. I also tested the Bonsai model on my test laptop; initially, its context window was too small (8k and 16k could not accommodate the FreeCAD MCP instructions), but even after increasing it to 32k, it proved useless for generating FreeCAD models so far. I've used Claw Code, Aider and Open Code with my server so far, and for this test I ended up with OpenCode because it was easy to set up to use an MCP. Because none of my LLM services are set up to be multimodal (capable of processing both text and images in this case), I configured the MCP to return only textual feedback from FreeCAD. I am unsure if this is a major limitation, though I suspect it might be. My testing experience remains limited, with no clear successes yet. Part of the issue likely stems from my ability to provide effective instructions for modeling 3D objects (I am relatively new to FreeCAD, English is not my first language, and I lack a precise vocabulary for describing construction features to an LLM). Nevertheless, the LLM has demonstrated the capacity to create 3D models in FreeCAD. In one of my first tests, I asked it to generate a cube and then produce CAM/G-code instructions for a CNC machine. It did output G-code (which remains untested), but I was surprised to find that it bypassed FreeCAD's built-in CAM module entirely and instead generated an external Python script to produce the code. This was not quite what I intended, though my instructions were probably unclear. The Qwen model with OpenCode seems to strongly prefer programming directly; it frequently executes Python snippets inside FreeCAD to achieve its goals rather than using the standard sketch-and-extrude workflow I am accustomed to. In another test, I asked the LLM to create a parameterized pipe assembly to see which of FreeCAD's parametric tools it would choose, but found no evidence of traditional parametric features in the output. When prompted, the LLM explained that the parameters were embedded directly in the Python script used to generate the model, rather than in native FreeCAD features. With more explicit instructions, it eventually created a FreeCAD spreadsheet to manage the parameters. The resulting model looked much closer to my expectations and could have been useful with further refinement. My so far last experiment was less successful: I asked it to design a pipe clamp, but the LLM repeatedly failed to position the clamping screws in a way that would actually secure the brackets around the pipe. It is unclear whether this limitation lies with the model, my prompt, or other factors. Based on my testing so far, I am uncertain whether FreeCAD MCP is merely a fun toy or a genuinely useful tool. I will only commit time to maintaining it in Debian if it proves to be practically valuable. I would welcome feedback from anyone who has experience with the project, preferably via the original request-for-packaging mailing list thread. Alternatively, I am available in the FreeCAD and Debian AI IRC channels for further discussion. As usual, if you use Bitcoin and wish to support my activities, please send donations to 15oWEoG9dUPovwmUL9KWAnYRtNJEkP1u1b.

2 August 2026

Russ Allbery: Term::ANSIColor v6.0.0 TRIAL release

Yesterday, I uploaded Term::ANSIColor v6.0.0-TRIAL to CPAN for early testing. This release will raise the minimum required Perl version to 5.12, dropping support for Perl 5.8 and 5.10. When I did the same with podlators a couple of years ago, it upset a few people and one of them asked me to make this sort of test release in the future. Hopefully this will help. I have not run the normal release machinery and haven't archived this release in the normal places, since I intend it to be transient. It's only on CPAN, where people can retrieve it for testing. Once v6.0.0 is released, few traces of this TRIAL release will be left. This doesn't appear to be how other people use the TRIAL mechanism, but it felt more comfortable to me. If I have to make substantial changes, I'll consider changing my approach. I plan on turning this into the v6.0.0 release in about a month or two, hopefully with only documentation changes. Term::ANSIColor is a "very upstream" core module with a lot of dependencies, and CPAN (unlike some of the archives that followed it, such as PyPI) doesn't support conditionally retrieving packages based on the current Perl version. This release may therefore be disruptive for people who are still trying to support Perl 5.8 and 5.10, since CPAN installation tools may attempt to install an incompatible Term::ANSIColor version. I'm sad that this will be the result, since I know some people still care about those versions. I'm pressing forward with updating my Perl modules anyway, though. I realized that honoring other people's desire for stability to such a degree that I was unable to use Perl features added more than 15 years ago was destroying my motivation to work on these Perl modules at all. So I've decided on a very slow and gradual approach where I'm going to keep pushing the minimum supported version forward but try to give people a lot of warning. Personally, I think it's time to let ancient versions of Perl go and follow the Lyon Amendment about supported Perl versions. When we're talking installing new modules for software released more than 15 years ago, we're talking about special limited environments and retrocomputing more than what I would consider routine software maintenance. Those tasks should expect to need different tools and a different workflow so that they can pin historical versions. Since this isn't something I'm personally interested in, my willingness to expend time and energy to assist is limited. As you can probably tell, I still feel nervous about pressing forward in this way, but I think this is the approach that lets me continue to enjoy maintaining these Perl modules. It's been 29 years for Term::ANSIColor, but I still enjoy fixing bugs in it and putting out a new release from time to time, particularly if I can clean up the code a bit each time I touch it.

31 July 2026

Otto Kek l inen: Estonia, the country of the fit and the wit

Featured image of post Estonia, the country of the fit and the witWhile many Western democracies seem to be in a state of decay and are no longer the safe, civilized and prosperous countries they once were, there are still some European countries that are governed well. One of those that stand out is Estonia. Estonia is probably most well known for multiple software companies that originated from there, such as Wise, Bolt, Pipedrive and Skype. The government itself is also famous for being early in issuing government IDs with an embedded smart chip for online authentication already in the 1990s. Via the national portal at eesti.ee all residents can access extensive eServices ranging from viewing their health benefits to filing taxes. Estonia has also been running an e-Residency program since 2014, where they issue digital ID cards to foreigners, making it easy for them to remotely log into the government portals and for example, establish businesses, file annual reports and so forth. Note that the e-Residency is not a path to physical residency. Estonia does, however, have a separate Digital Nomad visa program that makes it easy for non-EU citizens to also physically establish themselves in Estonia, assuming, of course, you meet the criteria, which includes, among others, a minimum monthly income of 3960 from outside Estonia. EU citizens naturally have free mobility inside the EU and can simply get an apartment and register as a resident in Estonia if they so choose. And there are plenty of reasons to do so.

Estonians value health, education and entrepreneurship I moved to Estonia about one and a half years ago. In my observations Estonia strikes me as a country that values health, education (in particular programming and natural sciences) and entrepreneurship highly. I don t know how Estonians achieve it, but they look pretty fit and rarely obese. Estonia has rye bread and sauna in their culture just like Finland, and in addition the flat terrain and well-planned bike routes and extensive network of parks (and pull-up bars everywhere) seem to create an environment where it is easy to live in a healthier way. The consumption of processed foods and candy also seems relatively low among Estonians. The gym chain MyFitness also seems to be present everywhere. Even the Tallinn airport has a calisthenics workout station right at the departure gates, which anyone is free to use while waiting for their flight to take off. One of the top longevity influencers in Europe, Siim Land, is Estonian. Estonia has lots of good bike paths, parks and outdoor gyms There is even a calisthenics station with pull-up bar and more at the departure gates at Tallinn airport Estonians also seem to value the school system highly. The government has been actively raising teacher pay and has a stated goal of reaching 120% of the national average by 2027. The students are also expected to value the education and respect their teachers. According to the TALIS 2024 survey (OECD s international teacher survey), Estonian teachers spend significantly more time on actual teaching and learning and waste less time on interruptions or keeping classroom order compared to the OECD average. This is among the highest rates internationally, meaning they spend relatively little time on maintaining order or dealing with disruptions. While the international education benchmark PISA scores have been dropping globally, Estonia has consistently been climbing the ranks in past decades. In the latest PISA study (from 2022), Estonia ranked number one in Europe for reading, mathematics and science. In the overall results, Estonia ranked seventh globally, only behind countries such as Japan, Korea and Singapore. Valuing entrepreneurship is evident in how the taxation system is set up in Estonia. Famously, in Estonia, companies can defer taxes on annual earnings and reinvest all of their profit in growing the company. Taxes are due only later, when paid out from the company, for example as dividends. For individuals, receiving dividends from any Estonian or foreign company is tax-free as long as the company paying dividends already paid corporate tax on the same income. The tax system is also very simple. For all individuals, all types of income, including salary and capital gains, are always taxed at a flat rate of 22%. This removes the incentive for anyone to try to convert income into different types, setting up holding company structures and other optimizations as there is no gain. All entrepreneurs can simply focus on growing their business and forget extra bureaucracy. There is also no marginal tax rate cliff to stop working at everyone is encouraged to always try to produce as much value as they can. A simple tax system is also reflected in the fact that anyone can easily read all tax rules that apply to individuals in plain English on the Estonian tax authority website, and one does not need to hire any accountants simply to file taxes. Estonia also has a very straightforward investment account system: any person can freely open a self-directed investment account at any brokerage at no extra cost and report it as such to the tax authority, and then use it to save for an apartment, retirement, or other purposes, and defer all income taxes until withdrawal. There are no caps or time limits, and all residents are encouraged to save and invest as much as they can and thus take responsibility for their own wealth accumulation. It seems that culturally Estonians respect people who are active and progress in their careers and businesses more than in other countries. Unlike in Finland, successful people are admired and living on government welfare is not romanticized. At the same time, the government benefits are less generous so people can t live comfortably on them and, for example, many of the asylum seekers Estonia accepted have since left on their own initiative to other European countries in search of better benefits.

Low crime, high trust Another thing that strikes me when walking the streets of Tallinn is that there are no drug addicts, beggars, thugs or the like. The difference compared to, for example, Vancouver (where I lived previously) is stark. In public buildings, people leave their coats and bags hanging in the lobby while visiting. Private houses and apartment block yards are not fenced. In my building, I noticed people even leave their bikes unlocked in the bike shed. I have also seen the staff of a coffee stall in a shopping mall going for a break and leaving everything unattended, not worrying that anyone would take anything while the staff is away. Nobody is stealing anything from the unattended coffee shop while staff is having a break at  lemiste shopping mall This is not just my personal experience. According to the Numbeo crime index, Estonia has one of the lowest crime rates in the world. Also, comparing drug and property crime stats, for example, Finland has twice as much crime per capita, and places like Vancouver in Canada almost five times more. I don t have any clear explanation for why crime is so much lower in Estonia, but some suggest that higher social cohesion and lower levels of welfare contribute to people standing to lose more if they behave antisocially. Compared to Finland, Estonia also more readily jails repeat offenders, and those who are put on trial will experience a swifter court process thanks to simplified legal processes and more efficient governance.

Moving to Estonia: quick checklist Moving to Estonia is very easy for any EU citizen, in particular if your work is not location-dependent (e.g., remote work or an online business) and you are simply looking for the cleanest and safest environment to live in. First, check into a hotel in Tallinn, check out various neighborhoods to figure out what area you like (my favorites are Kalaranna, Kalamaja, Noblessner and Volta) and start browsing available apartments in English at kv.ee. Most professionals speak fluent English, so there should not be any difficulty in reaching out to people by email or phone. Tallinn is famous for the old town The economic boom of recent decades created a lot of new construction, with Kalaranna being among the newest areas The next step is to buy a local prepaid SIM card at e.g., an R-Kiosk or a convenience store as signing up for other matters later on will require an Estonian phone number. Once you have an apartment and e.g., signed a rental agreement, you can register in the population registry online. After that, you have proof you are a local resident with an address and telephone number in Estonia. With local resident status, you can go to the police station to get a local ID card. Don t bother scheduling an appointment, just go to the Tammesaare police station in Tallinn, take a queue number and wait. Once it is your turn, they will guide you on how to use the photo booth, fingerprint registration device, and file your application. A few days later you will receive an email confirming whether your application was accepted, and after a few more days, you will get another email notifying you that your ID card has been printed and is available for pick-up at the same location. This will also be your first practical experience of how fast and efficient the government in Estonia is. Once you have the local ID card, you can use the smart card feature to log into all the government eServices and sort out the rest of the relocation process, such as registering tax residency and getting a family doctor. The main eServices portal in Estonia: eesti.ee

How did Estonia evolve to be like this? After Estonia regained its independence after the fall of the Soviet Union in 1991, the first elected government in 1992 was led by a very progressive 31-year-old Prime Minister Mart Laar, who managed to set up some very good policies and laid the foundation of a society that has evolved well in the decades since. Estonia was very lucky to have people in power in the 1990s who didn t simply copy what other Western countries were doing, but who tried to think about things from first principles and create Estonia s own model for efficient and fair governance. As a post-Soviet country, the population had also been vaccinated against overly socialist and unrealistic ideals, and everyone had a healthy distrust of the government s ability to solve problems and emphasis was placed on people s liberty to work for themselves as they best see fit. The improvement in living standards over the past 35+ years has also been witnessed by the population, and voting behavior supports keeping the country on the same trajectory. General living standards still continue to improve as the nominal wage growth sits at around 6%, clearly above the annual inflation rate of about 3%. In 2026, the Estonian economy is expected to grow about 2.4%, which is faster than the EU average. The growth in Estonia is not the result of any accounting tricks - Estonia is part of the euro and can t print its own currency, nor has it been funding the public sector with excessive debt. With a 24% debt-to-GDP ratio, Estonia consistently ranks as one of the most responsibly managed countries among advanced Western economies. As wages in Estonia soon catch up with the EU average, and higher defence spending has forced the government to raise taxes in recent years, the economic growth that Estonia has enjoyed for 35+ years since it exited the Soviet Union might slow down a bit in future years. The policies that fueled this growth in living standards, however, are likely to stay.

The tiger leap There is one specific government policy in Estonia s history that I think should be highlighted in particular. Estonia was very progressive by announcing the Tiigrih pe (Tiger Leap) program in 1996 with the goal of equipping all schools with computers and teaching all students the basics of programming. This surely had a large influence on why Estonia has so many successful software companies, why the government eServices are so mature that even neighboring countries like Finland are striving to copy the Estonian government s IT architecture called X-road. The Tiigrih pe project was originally suggested in the mid-1990s by Toomas Hendrik Ilves, then ambassador of Estonia to the United States, Canada and Mexico, and later President of Estonia in 2006 2016. While he was a psychologist by education, he was also a self-taught amateur programmer and used his political influence to promote sensible adoption of information technology in both Estonia and the EU. The history of Estonia has several prominent figures who were not lawyers by profession but engineers, scientists and historians who were very practical in their political decisions, which I think is now reflected in how government processes were formed. The video below shows how the Estonian government advertises itself and what values they choose to highlight:

Should other countries adopt policies from Estonia? Of course, not everything is perfect in Estonia either. The fertility rate of 1.16 in Estonia is very low. This trend is present globally, but in Estonia it is way below the EU average. Also, the service culture is something that needs to improve in Estonia. While services are in general fast and efficient, the attitude of people working in cafes and stores does not reflect a willingness to fill in gaps if the standard process falls short, nor are visitors actively made to feel welcome as individual humans, but are treated as mere process inputs. However, many of the things listed earlier I think should be studied by policymakers elsewhere. Societies are complex systems and there is of course no guarantee that copying a single policy to another country with different ethnicities, history and ingrained culture would lead to the same policy outcomes. But considering that Estonia is a small country without favorable geography and no natural resources, and that it started out from a place of total chaos, low economic activity and high crime in 1992 to rise to what it is now in 2026, the success it has seen is surely largely a result of good policies, governance and culture that other countries can and should mimic.

30 July 2026

Clint Adams: not ninpo

The UX of jj's builtin merge editor finally became too much for me. So, I looked at the list of merge tool options, saw vimdiff, and thought, Oh, cool, I know how to use vimdiff. So, I launched jj config edit --user, added a ui section, and set merge-editor to vimdiff. With the new config, I ran jj resolve again. It was at that point that I realized that I do not, in fact, know how to use vimdiff: I only know how to use vimdiff with two buffers. What appeared in my terminal was a 4-pane monstrosity. Why are there four panes? I'm trying to resolve conflicts between only two changes on only one file. For a moment, I nearly go down a rabbit hole, because this says that by default, vimdiff is barely useable [sic]. Should I be installing some addon or a Python script? Apparently there are tradeoffs. I just want to resolve these conflicts without doing line-by-line approvals for how ever many hours that would take. Accordingly, I ran away in terror, installed meld, set merge-editor to meld, and went clicky-clicky in the GUI. I'm not happy using a GUI, but at least it didn't have a mysterious extra buffer to confuse and taunt me.
Posted on 2026-07-30

27 July 2026

Dirk Eddelbuettel: #057: Conditionally Quieten Compilers

Welcome to post 57 in the R4 series. R packages with compiled codes can use the file src/Makevars to set compilation flags. We often rely on this to set libraries, include directories or compilation options. When using external libraries, be it header-only or via headers and linking, we are often experiencing compilation noise when these libraries tickle warnings under generally-recommended flags such as -Wall -pedantic. Two packages I maintain are clearly repeat offenders here: Eigen, and BH. Both cam generate pages and pages of compiler output. This is generally not great as it may hide genuine warnings from our own code. What makes matters worse is that some of the available and specific options for the compilers are treated by R CMD check as non-portable leading to a nag on package checking. Examples are -Wno-parentheses, -Wno-maybe-uninitialize or -Wno-nunnull. I have long resorted to adding these to my per-user ~/.R/Makevars. When added there, compilation is quieter, but R CMD check still nags here where the option is set but not at CRAN or r-universe. A situation that is not ideal but what somewhat stable . More recently, I realized there was an available check we can use to conditionally add extra compilation flags but leave them off by default. That makes local development quiet allowing us to focus on the quality of our additions here without noise from third-party libraries we may use. At the same time we do not need to do anything else to let CRAN do its work. The check we now use is whether there is a .git/ directory present. If so, we are indeed building from local sources and can add extra flags. If not, we are likely building from a tar.gz source archive which is the case for CRAN and hence do not set these. An example use is this recent additional to package qlcal where this bit of R code is invoked from a minimal shell script configure and replaces the stub @XTRAFLAGS@ in src/Makevars.in (or src/Makevars.win.in)
if (dir.exists(".git"))  
    ## development from a .git directory can use these flags
    xtraflags <- "-Wno-nonnull -Wno-deprecated-declarations"
  else  
    ## else build from tarball so stick with existing flags
    xtraflags <- ""
 
win <- if (Sys.info()[["sysname"]] == "Windows") ".win" else ""
infile <- file.path("src", paste0("Makevars", win, ".in"))
outfile <- file.path("src", paste0("Makevars", win))
lines <- readLines(infile)
lines <- gsub("@XTRAFLAGS@", xtraflags, lines)
writeLines(lines, outfile)
With this change, local compilation is quiet, yet CRAN has nothing to nag about (as seen at the qlcal results page). Similarly, one can also check from an actual configure file written in autoconf. Here is a similar example from RcppEigen (showing some relevants parts of the whole file)
# PKG_CXXFLAGS initialized earlier ...

## Check if building locally
AC_MSG_CHECKING([whether .git/ exists])
if test -d "$srcdir/.git"; then
    AC_MSG_RESULT([yes, adding extra flags])
    AC_SUBST([PKG_CXXFLAGS],["$ PKG_CXXFLAGS  -Wno-ignored-attributes -Wno-maybe-uninitialized"])
else
    AC_MSG_RESULT([no, consider adding '-Wno-ignored-attributes -Wno-maybe-uninitialized' to ~/.R/Makevars])
fi

AC_SUBST([PKG_CXXFLAGS], ["$ PKG_CXXFLAGS "])
AC_CONFIG_FILES([src/Makevars])
AC_OUTPUT
Once again, with this change compilation is quiet locally, yet unaffected at CRAN. Just what we want. Give it a try in your packages.

This post by Dirk Eddelbuettel originated on his Thinking inside the box blog. If you like this or other open-source work I do, you can now sponsor me at GitHub.

Valhalla's Things: Late Victorian Vampire Shirt

Posted on July 27, 2026
Tags: madeof:atoms, craft:sewing, FreeSoftWear
A woman wearing an old-style white shirt with lots of fullness, wide and long sleeves and ruffles at the collar that spread out framing the neck, down the center front to underbust height, covering the slit and at the cuffs, reaching to mid-hand. The shirt is gathered at the waist with a belt, and worn over the bottom garment to show that it reaches to mid tight. Drama levels in the pose are pretty low. The recurring joke is that because of some health issues, in summer I dress like a Victorian Vampire. But how would an actual Late Victorian Vampire dress? Picture her, she would look like some kind of eccentric gentlewoman, as vampires usually do, probably with a style that is a bit conservative, rather than following the latest fashions. Same woman, same shirt, posing as a vampire ready to attack a victim. Drama levels increasing. Now, she wouldn t probably wear men s shirts. But what if she was a lesbian1 vampire? Wouldn t she need a fancy, frilly shirt to go with her tailored cycling suit when she s out seducing the more active ladies in the neighbourhood? Or maybe not. It s not making a lot of sense, is it? But I do have a lot of shirt fabric in my stash2, and I could use a few more shirts that were practical and comfortable, but also somewhat over the top. For the practical and comfortable I went to my trusted 1880s shirt, while for the over the top part I looked at inspiration from the earlier 18th century frilly shirts, and their later imitations. I decided to use some nice cotton batiste I had bought quite a few years ago to make one of my first historically inspired shirtwaists: I may have a tendency to buy a bit more fabric than actually needed by the pattern, but that s what everybody does, right? For the ruffles I decided to use a lighter weight cotton voile, also from the stash. the top edge of a ruffle being whipstitched over some gathered fabric; the rest of the unfinished shirt is visible in the background. At the front, I wanted the ruffle to be inserted in the yoke, but I was also whipstitching the gathers to it to make them neater, so I started bu attaching the yoke lining to the gathered front, then I whipstitched the ruffle to the front, catching each gather, and finally I whipstitched the other yoke on the ruffle and the rest of the gathered front. The front of a shirt: the body was gathered into a yoke, but it has been unpicked and pulled out to extend a bit past the end of it, into where the collar will be sewn. And then after sewing the collar, I realized that this way the slit would have remained open in the front (or the collar too narrow), so I had to unpick the front part of the yoke, and sew it again, this time leaving an excess of fabric as wide as half the placket width from the pattern, to be sewn directly in the collar band. From then, things progressed smoothly, with some interruptions, until I got to the first sleeve, which I failed to insert twice, as one does. The same shirt worn without the ruffle at the collar, with just what looks like a mandarin collar, closed with a clip with an amethyst. Drama levels have gone way down. On the third attempt, with a different method, I succeeded, I tried the shirt on, and it already felt extra. Close up of the collar on a table: at the center back of the shirt collar there is a buttonhole, and a double button is used to keep the detached collar in place, while at the front both the shirt collar and the detached collar have buttonholes. But it could be even more extra. With some ruffles also at the collar. Same close up, but now the collar has been closed with a clip-on earring with an amethyst and some small fake clear stones, and it looks as if the skirt had a ruffle collar and a jewel button (or a pin). The shirt had been made with a simple collar band, and I could have just added the ruffle to it, but I also wanted to be able to wear it with other detachable collars, so I decided to make another collar band with ruffles, to wear on top. And that was mostly it, except for the reinforcement patches at the side seams and cuffs: I love having them, because they make the seam end neater and stronger, but they are a bit of a hassle to make, so they got postponed a few days. Same woman and shirt, back with the ruffled collar, in a pose like that of an artist that is fainting for futile reasons. Drama levels over the top. But finally, the shirt was done. And I tried it on, and it was good. But now I really need a pair of cycling breeches, don t I?

  1. ok, maybe straight passing bi? anyway.
  2. I have no idea how they got there.

20 July 2026

Jonathan Dowland: Interzone digital

(no, this isn't a blog post about Joy Division songs) Last time I wrote about Interzone, I was discussing issue #294, the first published under new management in a paperback-sized format ("JB6"). The format and presentation of the magazine was fantastic: it fit in a lot of my pockets, and was packed with 15 stories as well as the regular columns, in full colour with fantastic layouts and illustrations. Sadly there was only one more physical issue before Interzone was forced to become a digital-only publication.
IZ issues 294 and 295 IZ issues 294 and 295
I don't want to dwell on the sad necessity to move to digital. Interzone continues on, celebrating the milestone issue #300 in 2024. Subscriptions are managed via Patreon. Issue #305 just came out. Instead I wanted to write a small bit about how I engaged with the paper magazine, and the difficulties I've had trying to engage with not just Interzone but any magazine-style publication in a digital context. With most fiction, I read linearly: start the beginning and read to the end, in order. That works well for me with e-readers. But for magazines (and most non-fiction) I don't, I jump around: usually starting with the table of contents, I might pick a short column to start, or jump into the middle of the "book reviews" section to read about a specific book. I might skip sections entirely. I find it very difficult to read like this with an e-reader. I think this is partly because I reference the depth of the paper book or magazine, its thickness, to orient myself. But it's also partly the limitations of e-ink.
My tick-list for an issue of IZ My tick-list for an issue of IZ
For print-Interzone, I used to start by inserting a small piece of paper inside the cover (the delivery slip was ideal). On this I listed the stories within and ticked them off when I read them (sometimes I double-ticked if I really liked a story). That helped me to remember, perhaps months or years later, whether I'd read all the stories or not, and which I liked. I could do something similar on some e-readers: the Remarkable for instance. But it's far from convenient to do on most e-ink devices. Interzone digital is available as both ePUB, the most common format for e-books, and PDF. For reading on my regular Kobo e-reader, PDFs don't work very well at all. I think this is generally true of most e-readers. Interzone was (and is) a well-designed magazine. The value of it was not just the content of the text, but the context: how the stories were presented; the accompanying art (most often colour in recent decades), but also the typesetting. ePUB doesn't specify much of that stuff exactly: it leaves that up to the client and the client's preferences. And there's a lot of advantages to that: Prefer a different font face or size? No problem. And most importantly for accessibility: If reading in ePUB makes Interzone available to more readers then that's a great thing. But sadly a lot is lost, IMHO.
IZ #305 on iPad Mini IZ #305 on iPad Mini
The solution I'm trying is to read the PDF version on the iPad Mini I resurrected earlier in the year. Despite being an Internet tablet, since it's not really usable for browsing the web anymore it's strangely still a distraction-free device. In fact it's pretty much single-purpose for reading Interzone and the odd other book which benefits from being read as PDF. I can appreciate the stylistic choices made in the page-setting as they were intended; I can quickly jump around the issue without waiting for an e-ink refresh; I get full colour; and whilst it would be tiring to read for a long time on the iPad screen, for the length of articles or stories in a magazine, this isn't a problem. It's not a solution for tracking what I've read (that version of ipadOS is too old to support clumsily scrawling on PDF pages with your fingers, at least in the Books app) but it otherwise seems to work well, so I'll see how it goes.

18 July 2026

Bits from Debian: DebConf26 welcomes its sponsors

Alt DebConf26 by Romina Molina DebConf26, the 27th edition of the Debian conference is taking place at the Facultad de Ingenier a en Ciencias H dricas of the Universidad Nacional del Litoral, in Santa Fe, Argentina. We appreciate the organizers for their hard work, and hope this event will be highly beneficial for those who attend in person as well as online. This event would not be possible without the help from our generous sponsors. We would like to warmly welcome the sponsors of DebConf26, and introduce them to you. We have two Platinum sponsors. Our Gold sponsors are: Our Silver sponsors are: Bronze sponsors: And finally, our Supporter level sponsors: A special thanks to the Facultad de Ingenier a y Ciencias H dricas - FICH UNL, our Venue Partner! Thanks to all our sponsors for their support! Their contributions enable a diverse global community of Debian developers and maintainers to collaborate, support one another, and share knowledge at DebConf26.

15 July 2026

Dirk Eddelbuettel: qlcal 0.1.2 on CRAN: Fresh Upstream Updates

The twentieth release of the qlcal package arrivied at CRAN today, and has been built for r2u. This version synchronises with QuantLib 1.43 released today as well. qlcal delivers the calendaring parts of QuantLib. It is provided (for the R package) as a set of included files, so the package is self-contained and does not depend on an external QuantLib library (which can be demanding to build). qlcal covers over seventy country / market calendars and can compute holiday lists, its complement (i.e. business day lists) and much more. Examples are in the README at the repository, the package page, and course at the CRAN package page. This releases updates to several new calendars (see below), and extends the calendars for Israel to some added new conventions, updates a few helper functions, and turns on ccache for continuous integration builds. The full details from NEWS.Rd follow.

Changes in version 0.1.2 (2026-07-14)
  • Synchronized with QuantLib 1.43
  • Calendar updates for India, Israel, and South Korea; small interface update for Israle
  • New calendars for Croatia, Malta, Montenegro, North Macedonia, Serbia, Slovenia, Uzebekistan
  • Updates to a number of QuantLib helper functions
  • Continuous integration now uses ccache via a setup action

Courtesy of my CRANberries, there is a diffstat report for this release. See the project page and package documentation for more details, and more examples.

This post by Dirk Eddelbuettel originated on his Thinking inside the box blog. If you like this or other open-source work I do, you can sponsor me at GitHub.

14 July 2026

Jonas Meurer: zed-xdebug

Nextcloud PHP debugging with Xdebug in Zed editor I started to switch from PhpStorm to Zed as IDE recently as Zed is open source and has a much smaller footprint and is more slick than PhpStorm. One thing that I didn't get running immediately was Xdebug integration, so I did a bit of research and asked Claude for help. Here's a quick writeup of how to get it running. I have Zed installed as Flatpak on a Debian Trixie host system. The PHP process runs in a nextcloud-docker-dev Docker container.

Install Zed and configure debugging there Install Zed: flatpak install flathub dev.zed.Zed In Zed: open the Extensions view and install PHP. Configure the debugger: Create ~/.var/app/dev.zed.Zed/config/zed/debug.json:
[
   
    "label": "PHP: Listen to Xdebug",
    "adapter": "Xdebug",
    "request": "launch",
    "port": 9003,
    "pathMappings":  
      "/var/www/html":             "/home/<user>/devel/nextcloud/server",
      "/var/www/html/apps-extra":  "/home/<user>/devel/nextcloud/server/apps-extra",
      "/var/www/html/apps-shared": "/home/<user>/devel/nextcloud/apps-shared"
     
   
]
Add one entry per bind-mounted app directory. After creating the file, restart Zed. Inside Zed, select "debugger: start" from command palette and then "PHP: Listen to Xdebug". Verify Zed is listening. Running ss -tlnp grep 9003 on the host should show *:9003 with Zed as the process.

Configure Xdebug inside the container /usr/local/etc/php/conf.d/xdebug.ini:
xdebug.mode = debug
xdebug.idekey = PHPSTORM
xdebug.trace_output_name=trace.%R.%u
xdebug.profiler_output_name=profile.%R.%u
xdebug.output_dir=/shared/xdebug
xdebug.log = /var/log/xdebug.log
xdebug.log_level = 3
; Try to discover the client host, otherwise fall back to the docker host
xdebug.discover_client_host=true
xdebug.client_host=host.docker.internal
; When you cannot specify a trigger, use "xdebug.start_with_request = yes" to autostart debugging for all requests
; https://xdebug.org/docs/all_settings#start_with_request
xdebug.start_with_request = trigger
; Set xdebug.mode trace to use this
; More details at https://derickrethans.nl/flamboyant-flamegraphs.html
xdebug.trace_format=3
xdebug.trace_output_name=xdebug.%R.%u
Apply changes by restarting apache in the container: apache2ctl -k graceful Notes:
  • host.docker.internal resolves on Linux Docker only if the container was started with --add-host=host.docker.internal:host-gateway (nextcloud-docker-dev already does this).
  • discover_client_host = true makes xdebug follow X-Forwarded-For - useful behind Nextcloud's dev reverse proxy.

Test xdebug with a PHP command inside the container Run XDEBUG_SESSION=PHPSTORM php occ status inside the container and check /var/log/xdebug.log.

Install the browser extension Install Xdebug Helper (Firefox/Chrome). In its preferences, set the IDE Key to PhpStorm. It will set the XDEBUG_SESSION cookie when toggled to Debug. Click the Xdebug Helper icon in the browser and set it to Debug.

Test Xdebug with browser extension Load the URL that exercises the code path with the breakpoint. Zed should stop the code exection at the breakpoint.

11 July 2026

Reproducible Builds: Reproducible Builds in June 2026

Welcome to the June 2026 report from the Reproducible Builds project! In these reports, we outline the most important things that we have been up to over the past month. As a quick recap about what problem our project intends to solve, whilst anyone may inspect the source code of free software for malicious flaws, almost all software is distributed to end users as pre-compiled binaries. The motivation behind the reproducible builds effort is to ensure no flaws have been introduced during this compilation process by promising identical results are always generated from a given source, thus allowing multiple third-parties to come to a consensus on whether a build was compromised or not. If you are interested in contributing to the project, please visit our Contribute page on our website. In this month s report, we cover:

  1. Only installing reproducible packages with repro-threshold
  2. Distribution work
  3. diffoscope development
  4. From our mailing list
  5. Documentation updates
  6. Patches
  7. Four new scholarly papers


Only installing reproducible packages with repro-threshold A very interesting demonstration is now available showing how you might configure your Debian system to only install packages that have been reproduced by m/n rebuilders. This is implemented via a reproduced+https:// APT transport ( a mechanism for communicating between the APT client and its repository source commonly HTTP):
Every package download is intercepted by repro-threshold, which queries two independent rebuilders for a signed attestation before allowing installation to proceed. [It] is important to note that [an] install will only succeed if all package dependencies are also reproducible.
The demo gives examples of how to quickly experiment with this using a Docker container.

Distribution work In Debian this month: The IzzyOnDroid Android APK repository reached its next milestone this month, now covering 2 out of every 3 apps (66.7%) with reproducible builds. Their documentation for debugging and fixing failed builds has steadily grown as well. More clients have picked up showing reproducibility results (e.g. Droid-ify), and Neo Store now can be configured to stick to only reproducible applications. Further, an independent builder has been added to the build farm, increasing the trust level even more as APK builds can have multiple confirmations now. At the same time, IzzyOnDroid s rbtlog got several new features. The most outstanding is caching for frequently used resources such as reproducible-apk-tools, command-line tools and NodeJS in order to counter ongoing issues with GitHub availability, while at the same time saving bandwidth and build time. This change also enables some other some smaller enhancements such as being able to configure build timeouts per recipe for those builds running longer than the average, release pattern filtering for update checks or having a field for maintainer notes to shortly summing up e.g. why a reproducible build failed.
Lastly, Bernhard M. Wiedemann posted another openSUSE monthly update for their reproducibility work there.

diffoscope development diffoscope is our in-depth and content-aware diff utility that can locate and diagnose reproducibility issues. This month, Chris Lamb made the following changes, including preparing and uploading versions 319, 320, 321, 322 and 323 to Debian:
  • Debian adds an extra Flags: line in the output of ocamlobjinfo, so adjust the test for cross-distribution compatibility. [ ]
  • Bump debhelper compatibility level to 14. [ ]
  • Fix compatibility with Ocaml 5.4.1. [ ]
  • Use --long-form-style arguments when calling apktool in order to support apktool version 3. [ ]
  • Support Androguard version 4 and previous versions at the same time. [ ]
  • Update copyright years. [ ]
In addition, Jochen Sprickerhof added better header detection for the Sphinx documentation system [ ], Michael Daniels fixed the tests when run with zipdetails version 4.006 [ ] and Zbigniew J drzejewski-Szmek added a version of the deprecated os.path.commonprefix method [ ]. In addition, Vagrant Cascadian updated diffoscope in GNU Guix to version 321 and 323.
Chris Lamb also made the following changes to strip-nondeterminism, our tool to remove specific non-deterministic results from a completed build:
  • Skip symlinks when manually called via /usr/bin/strip-nondeterminism. (#1139000)
  • Update debian/watch format. [ ]
  • Drop Rules-Requires-Root: no and Priority: optional fields. [ ]
  • Bump Standards-Version to version 4.7.4. [ ]

From our mailing list On our mailing list this month:
  • kpcyrd posted to our mailing list regarding the waves of malware uploads to aur.archlinux.org . Curiously, every incident I looked at used npmjs.com for malware delivery , specifically where the npm package includes an (automatically executed) preinstall script that is an ELF binary.
  • kpcyrd also announced the release of debian-repro-status version 0.4.0, a tool written to give you an approximate idea of how viable it would be to enforce a reproducible packages only update policy for the computer system you ve built :
    The change updates dependencies to the latest versions, and adds support for multiple -H options, to query results from multiple rebuilderd instances. The results are also now fetched concurrently.
  • kpcyrd also reported that, whilst taking a screenshot for the above release, they noticed that the debian:sid container now is 100% reproducible.
  • Finally, kpcyrd also created a pull request against the add-determinism package to update the itertools and zip Python dependencies.

Documentation updates Yet again, there were a number of improvements made to our website this month including:
  • Chris Lamb added a reminder re. using the UTC variants of the Javascript Date methods. [ ]
  • Mattia Rizzolo moved OTF to the old sponsors list. Thank you for your support!. [ ]
  • kpcyrd updated the Rust documentation to recommend using the --release argument for consistency. [ ]

Patches The Reproducible Builds project detects, dissects and attempts to fix as many currently-unreproducible packages as possible. We endeavour to send all of our patches upstream where applicable or possible. This month, we wrote a large number of such patches, including:

Four new scholarly papers Kenichiro Muto and Kuniyasu Suzaki of the Institute of Information Security in Yokohama, Japan published an interesting paper this month titled Attestable Build Chain: Enabling Trust in Reproducible Builds (PDF). Their abstract is as follows: Ensuring trust in software supply chains requires verifying not only artifacts but also the processes that produce them. Although Reproducible Builds (R-B) require rebuilding to validate artifacts, they cannot verify whether the build was executed with the intended toolchain and inputs and may reproduce unintended or compromised builds without detection. We present Attestable Build Chain, a framework for externally verifying build-time execution without rebuilding. Rather than preventing compromise, it provides verifiable, tamper-evident evidence of actual build-time execution, enabling verification of build process integrity from observed file accesses during the build. [ ]
Julien Malka, Stefano Zacchiroli and Th o Zimmermann published a 50-page report detailing A Decade of Software Reproducibility in the Nix Package Ecosystem:
We find that functional package management enables extremely high rebuildability over time (near-universal ability to reconstitute historical build environments and rebuild software packages), while bitwise reproducibility has steadily improved and reaches a high point in recent years (up to 93% in 2024). Early years show substantially lower bitwise reproducibility, indicating that functional package management alone does not guarantee bitwise-identical outputs, and that the observed high level of bitwise reproducibility is not solely due to the package management approach. Common causes of unreproducibility, both in the rebuildability and bitwise reproducibility dimensions, include management of dates in build and test processes; we quantify their prevalence and other common causes using manual analysis of logs of rebuild failures and automated analysis of diffoscope.
A PDF of their report is available online
Tim Bastin of L3montree GmbH and Jacek Galowicz of Applicative Systems GmbH from DevGuard published a paper detailing How We Built a Sovereign, Reproducible Container Supply Chain for DevGuard:
This paper presents how the DevGuard project rebuilt its OCI container pipeline around reproducible Nix builds and independent dual-platform digest verification. DevGuard images are built hermetically from pinned source revisions, signed with Sigstore/Cosign, and verified through digest comparison across GitHub Actions and sovereign GitLab infrastructure hosted on container.gov.de. We describe the practical integration of reproducible OCI image builds into existing CI/CD workflows and argue that independently reproducible container digests provide a stronger integrity guarantee against build tampering than provenance alone. The paper further discusses remaining trust assumptions and the relevance of sovereign build infrastructure for government and regulated environments.

Finally, Yiseul Choi, Junga Kim, Jun-Ho Hong and Seongmin Kim of the Department of Convergence Security Engineering at the Sungshin Women s University in Seoul, Korea titled Attestation-based verification of SBOM integrity via consumer-side reproducibility:
Software bills of materials (SBOMs) support supply chain transparency, but they do not prove that a delivered SBOM reproducibly corresponds to its software artifact. Existing signing and provenance mechanisms protect integrity and traceability, yet lack consumer-side reproducible verification. We propose an SBOM integrity verification framework combining procedure disclosure, consumer-side reproduction, authority-generated reference evidence, and digest comparison. A trusted authority records a reference digest, and consumers compare it with locally reproduced and delivered SBOM digests. Experiments on 100 real-world container images show detection of artifact tampering, SBOM substitution, distribution modification, and adaptive tampering beyond signature-based approaches


Finally, if you are interested in contributing to the Reproducible Builds project, please visit our Contribute page on our website. However, you can get in touch with us via:

6 July 2026

Aigars Mahinovs: How to make a good group photo

Taking a good group photo consists of multiple aspects: I can say with confidence that nearly everything here comes from having failed to do these things right at least once, even on the latest attempts, so this is an ideal to reach towards, not something we expect to hit every time. The Goal The main goal of a big event group photo is capture both the moment itself and each individual person inside that moment. We want people, who were not there to see all the people involved and get an impression of what it was like being there. It needs to show the breadth and depth of people that make up this group, this project. And we want people who were there to be able to look back the next week, the next year or in ten years and remember - ah, yes, I was there, I was standing right there with this grin on my face next to this wonderful person and I was feeling great. Hardware Based on the goal we want to have high level photographic gear that is able to capture both a broad enough picture to encompass all the people and some of their surroundings to communicate the context (without undue distortions) and to deliver enough detail and resolution so that faces and facial expressions and underlying feelings of every single person in that group could be clearly seen and preserved. To both capture the context and minimise distortion the final picture should be just a bit wider than normal human field of view. That is about 50mm for a full-frame camera or 35mm for a typical 1.6 crop camera. You can go a bit wider if there are no better alternatives (as detailed in the scouting section), but be prepared that corners of the image will be distorted and not really usable (but we can fix that in processing step). Or you can go to unusual aspect ratios, like we did in Debconf 10. In the absence of a 100MP+ camera, you will need to be stitching together multiple frames to achieve resolution high enough to have enough pixels-per-face to see emotions clearly. This means that the photos you will actually be taking will be tighter than the overall field of view mentioned above. Still, a higher resolution camera body is preferable - nowadays 24MP-32MP cameras APS-C provide a good compromise between resolution and price, but 45-67MP full-frame cameras also exist on the market. Assume that we will be shooting in a bright environment, so most likely with quite low ISO settings, that means that high-ISO noise characteristics of more expensive cameras will not really play a role here. You will also not need very fast burst modes, even manual speed of one frame per second is sufficient. You will also want to get as much detail as possible out of your lens, and this is the most important part. You can do amazing work in all other steps of the process and have a great camera too, but if you pair it with a lens that is not sharp, then the end result will be disappointing. You want the lens that is sharpest corner-to-corner when stepped down to about f/8-f/11, that you can get for your system. You also want that lens to be about 85mm full-size sensor or 50mm for 1.6 crop size. Luckily that kind of range is also a great range for optical design and sharpest lenses are typically available in exactly these kinds of sizes. You absolutely want to have a fixed focal length lens, not a zoom lens. Even profession grade zoom lenses often deliver worse image quality compared to fixed lenses that cost less 1/10th of their price (when shooting in the same focal length). Newer design lenses are better than older lenses - optical design, coatings and precision manufacturing have advanced a lot over the decades. Retro look is great for mood, but not as good for actual resolution and clarity. You don't need to overpay for most expensive lenses because those often only improve image quality on lower F-stops. To encompass the whole group we will need to shoot at f/8 and in bright light, so the extra benefits of those f/1.2-capable super expensive lenses will not come into play here. We will have no use for a flash here. A tripod will be too restrictive when rapidly repositioning the camera between different parts of the panorama shoot. But a monopod might help with stability - I have not tried that myself, however. For my last photos I used a Canon EOS R7 (32.5MP) with Canon RF 50mm f/1.8 STM lens and considering an upgrade to Sigma 56mm f/1.4 DC DN for the next time. Scouting Scouting a good location for the group photo is another big chunk of a successful picture. The critical piece of the puzzle is lens-to-face distance. In order to keep everyone's face in-focus and have enough resolution on the farthest faces (without making nearest faces truly massive) we want to do everything possible to reduce the variance in lens-to-face distance - to reduce the difference in distance between closest and farthest face. The most effective way to do that is to have the photographer climb higher. To see this in action on the Debconf photos, compare Debconf6 (very high camera position, group on level ground - good) to Debconf10 (camera not too high, group on stairs, still good) and to Debconf17 (camera could not get high enough and the group is on flat ground - not great). Even the Debconf25 photo was suboptimal from this perspective. The Debconf23 photo was a very good example from the recent years - good height and also the group was positioned in a semi-circle so there were no people directly in front and very near to the camera. So you are looking for the highest point you could get to (even if that requires a special permission of key or a ladder) with a field large enough to fit the whole group comfortably. How to check that? Normally I simply take a photo from the top of the whole area and note down from there where the extreme corners of the group could be and still be fully seen in the shot - not blocked by trees, buildings and shadows. Then I go down and measure that space. Rule of thumb being - people in one horizontal line can stand 1 normal length step from each other and two horizontal lines can be half a step from each other vertically. So I can just measure a rough rectangle in steps, multiply the sides, multiply that by two and I have the rough number of people that can fit there for the photo. Once you have a candidate location or two, it is important to check them at the same time-of-day as you plan to do the photo (see organization section for that). You want to make sure that the whole area of the group is in the same illumination - if half of the group is in the sun and half in a shadow, then you will be having a very bad time later. The absolute ideal positioning for the group photo is to have everyone be in shadow, but still have enough bright skies and bright buildings in front of the people to give good illumination of the faces. Worst you can do is have the sun be behind the people (so all the faces are really dark) and second worst is have the sun be directly in front of the group, so that the faces are very well illuminated, but everyone's eyes are closed because they are being blinded by the sun. And sometimes all you can do is pray for some light clouds to provide for even and dispersed light. Debconf23 was very lucky that way. Another consideration is to how people are going to get to that place. You need to consider accessibility needs of people (it is ok, if it takes more effort or time, but it needs to be organized and communicated well in advance). And you need to consider how the big masses of people will be getting there - how to tell people where exactly it is and how to get there from various locations where people might be hanging out during the event? Having an alternate location indoors might be necessary if the weather report for the next days is not sufficiently predictable. We had to use that contingency in Debconf9, for example. Organization It's hard to take a good group photo if half of the group does not show up or is too late, so this needs some organization to happen smoothly. First of all you need to choose date and time for the photo. The photo does not take too much time from the schedule of the event and can be squeezed in after all the other events are already scheduled. In fact I prefer that as it allows you the flexibility of choosing the date based on weather conditions and time based on light and shadow conditions in potential photo spots. You don't want to choose the daytrip day as most people will be away and return times are not really predictable. You do not want to choose the morning after Cheese and Wine party for obvious reasons. First day and last two days are also sub-optimal as some people arrive late and some leave early for various personal reasons. Also you don't want it to happen just before Cheese and Wine either because then you'd have very little time and clarity to do the processing of the image on the same day. For timing, the best way, in my experience, is to schedule the photo directly after the end of talk sessions before a meal break - lunch or dinner. Typically in the Debconf schedule there are 2-3 daily breaks planned, say for Debconf25 there was lunch, afternoon break and dinner. Talks are planned to end ~10 minutes before those breaks (and meals) begin, so for example, afternoon break starts at 16:00 and all talks in the previous block end at 15:50. In such a case just schedule the "Group photo" event from 15:50 to 16:05. This gives people the info to go there directly from the end of all talks and that they will have sufficient time for break/meal afterwards. Do not forget to specify the location (as exactly as possible) in that event entry and make sure to post it at least two days in advance. People often want to wear something specific for the photo and thus need to know about it in advance. This also makes sure that people do not make alternate food plans for that specific break and don't leave the venue. Announce the date, time and the exact location as wide as possible, don't be shy. Announce and discuss mailing lists, IRC, Signal, Telegram, make sure the front desk knows in case anyone asks in-person, ... Check that it is again included in the announcements email on the day preceding the photo date. When the date has arrived, it is a good idea to check in early with people with special mobility needs to make sure they know where to go, how to get there and how much time they will need to be able to get there on time. As the final round of talks before the group photo is starting up, it is time to recruit "runners". I've had great success with this technique. The idea is pretty simple - for each room where people congregate (talk rooms, hacklabs, cafeteria, outside hackspace, front-desk, ...) go there and choose one person. You want to choose a person that you will recognise and remember among everyone else in the group, either because of who they are or what they are wearing, whatever works best for you. If they agree to help, instruct them to: "at end of talk, announce that the group photo happening now and the location, herd people towards the photo location, be the last person out, make sure there are no stragglers from this area behind you, when you arrive to the photo place I will assume that everyone else from this room is also now there, when you are there catch my attention and show this sign so I know for sure that it is all good and make sure that I did see it from you". With that sorted out all you will need to remember is how many runners you recruited and how many have reported in to figure out if everyone has now arrived or if we still have to wait for someone or some group. Then you will only have one last point of organization left - shaping the crowd into a group. People will not know what your vision for the group photo is, so you will have to give clear and LOUD instructions on where people should not be standing. Use clear, large gestures to support your words. You want to compact the group, have the people that just joined in the last moment and are standing to the side come deeper in and join the crowd. Have any holes in the middle of the crowd filled in. Forming a semi-circle instead of a blob helps with averaging face-to-lens distances. Make sure people are not in unexpected shadows. Make sure carried objects, like umbrellas of flags do not cover the faces of other people. Take the time to look at everyone face to make sure there are no people hiding behind someone's shoulder - typically they are not aware that their face is in fact not really visible. If there are such people, call them out and point directly at them and encourage them to step forward, if they wish to do so. You are the only one seeing the final picture now and only you can correct it before capturing the moment. So a few extra seconds here are worth taking, even if 300+ people are standing in scorching heat and waiting on you. When you are happy with what you are seeing, make sure to tell people clearly that you are now about to take the pictures and again remind them not to move and explicitly not to turn their heads to the side until you are done (this is the source of most of the extra work in processing). Be very loud and clear and make sure you have everyone's undivided attention before you start saying the important stuff. When done - say so. There will be other groups that will want to also have a photo taken after the main group is a bit more dispersed, so don't run away. Typically at least the T-shirt group will want a picture and also all the organizers. Final bit of organization during the group photo shooting itself is the sneaky self-insert. You may choose not to bother with it, or do it in the simplest way, like I did in Debconf6, but if you really want to blend in with the crowd, you need to have someone else take a photo of you in the exact same location at the same date and time from the same location. So you should already during shaping the crowd decide where you would fit in, it is easiest to blend in at the back of the crowd and to one or other side, so that it appears like you are just standing behind the shoulders of a couple peoples. Remember that spot - it is easiest if you stand in the exact same ground spot when your photo is taken. Just go down, recruit a volunteer to take your photo, make sure the settings are fixed to the same ones as for the group photo shots and have them take a handful of shots of you - one of you centered in the camera frame and a couple more with you more towards the corners of the frame. This distortion from being off-center in the frame may be important later. Preparation In addition to preparing the crowd for the photo, you also need to prepare yourself and the equipment. Make sure you have dusted your camera sensor and cleaned both inside and outside glass of your lens. It is usually a good idea to remove any filters from the lens. Install the hood, if that could help with blocking the sun flares. Make sure you have the right lens and that you have installed the right lens. For fixed settings I typically shoot in JPEG with RAW being there more like an emergency backup. The extra dynamic range of RAW could be used, but it is really complex to do that in combination with image blending and it is hard to get right, so I prefer an all-JPEG workflow and fix the dynamic range in the scene itself, before shooting. For Canon I am using the Standard profile that boosts the color saturation and sharpness a bit as I just enjoy that look and find it hard to get anything significantly better from RAW data even with a lot of effort. In any case make sure you have enough space on the cards to take at least 100 images and that you have a full battery. Do not use high speed burst setting because it is then too easy to take too many pictures at the start of the sequence and be stuck with your camera still in "Busy" state writing big RAW files to slowish SD cards and not allowing you to finish the full picture rapidly. You want to have the shutter speed at at least 1/100th of a second to prevent blur from both your hand movements and also from people in the shot moving around a bit (image stabilisation will not help you there). And you want to have the aperture to be around f/8 - lower apertures risk people in front or behind falling out of focus, make the lenses look less sharp. Higher apertures also start to become less sharp due to diffraction effects above f/8. ISO should stay as low as possible, ideally at ISO 100, but if there is not enough light then upping the ISO to 400 would be the first step that I would try to do and second would be decreasing the aperture to f/5.6. If there is too much light, then increasing the shutter speed should be the safe thing to do. As people start to arrive into the shooting location - check the exposure and nail down the settings, ideally in manual mode. Consider that left side could be a bit lighter or darker than right side. Err on the side of making the picture a bit too dark as there is more depth to darkness before cut-off compared to clipping on the high end. However, do not trust the exposure detection, instead take a picture and look specifically at skin tones in faces of people that already are standing in the photo area. Faces are the key bit and the exposure needs to be adjusted just to the faces and ignore darker of lighter clothing. Do some test shots and find settings where faces look not too bright, but also not very dark and fix those settings in manual mode. Now you are ready for the action. Shape the crowd, check the faces and the action can start! Execution During taking of the group photo you want to finish it fast, but at the same time you have to take the time to make it right. If you hurry too much under pressure, you risk being left with unusably blurry images and the whole effort wasted. Having already prepared and verified the manual settings makes it easier. When you are taking pictures, you have to remain as still as possible - even at very high shutter speeds even slow hand movements are still bad for image quality. So think of the movement as of biathlon athlete shooting the very middle of five, very separate targets - take a burst, reframe, then steady up for a second and only then take the next burst. 3 frames per burst are sufficient. 90% of the time the very first photo of a burst will be best. As you move from frame to frame, aim for just a bit more than half-frame overlap. This will give the opportunity to skip frames if all is good, but also have backup coverage of every face in case of problems. Proceed systematically, I typically start off on the top left of the crowd, then go right until the end of the line, then shift down half a frame and go left until the end and repeat until I am done with the crowd. After that it is very helpful to also immediately take photos of a "frame" around the whole crowd. Stitching process often distorts the frames in weird ways that leave holes in the resulting image that you can fill if you have a wide frame around the crowd. It is possible to compensate with creative cutouts in the final image (like Debconf9), but the more framing room you make, the more flexible you will be able to be with cropping of the final photo. The frame also gives you the opportunity to capture more of the context of the place and space. As an example, Debconf25 group photo in the end consisted from 9 images + 1 for sick people + 1 for me. I ended up missing the framing shots for bottom left, top left and top right corners. To get there I took 68 images. And in some years it was more than a hundred. Processing This part might be less stressful than taking the pictures from intensity perspective, but it lasts longer. Depending on you luck, skill and perfectionism it can take anywhere from 3 to 9 hours of work to complete. Before you start, however, you should first request things that you will need for other people. This can even be done before taking the actual group photo, but usually I forget. To finish the photo you will need three things: The first two you should be able to get from the respective organizers. The motto is harder. I typically try to ask the current DPL to come up with something describing the current mood of the project or of the event, but it is rare that it is that easy. Most of the time I came up with something as I was editing the photo and reflecting on what was the mood, the feeling, the mojo of this conference and of this year was like. Bend that around a recognisable phrase or expression, make it a bit more insider-relevant and you are on the right path. Some years this was the hardest part. For the panorama stitching I will describe the workflow that has served me good for years, but maybe there are better ways possible nowadays. Feel free to let me know! First I would save all photos taken and select one sharpest photo from every burst. Next I would select the minimal number of photos that appear to be covering the entire crowd. The fewer images you use, the better in the end because the most quality problems crop up in the areas where photos are getting stitched together. Fewer seams leads to fewer issues. Open Hugin (you will also need enblend and enfuse installed) and import your minimal set of images into it. Click the "Align" button and wait a while - the processor will be trying to figure out keypoints in each image and then try to match these points between the images to try to fit them all together into a single projection. To do that it will distort the images. This is the trial and error process part. You may need to add, remove or replace images to get the stitching to work or to work better. You may want to add more of the frame images to fill the ragged holes around the image. After initial alignment, go to "Move/Drag" tab and move the image a bit up in the projected field of view and make it a bit more central visually. That will help a bit with the distortions in the near-by people and people in the corners of the image. In the "Crop" tab set the initial crop - leave it generous, you can always crop more in later steps. Do not be afraid of leaving in sizable chunks of black homes, empty skies or grass. All of that can be filled in later as well. Go back to the "Assistant" tab and click "Create panorama". It is good enough to have JPEG output at 100% quality using exposure corrected low dynamic range output option. Make sure to check the "Keep intermediate images" option. This will not only generate the final, merged panorama, but also keep around the individual images after perspective correction and exposure blending steps. These are critical for fixing blending error in the next step. You might need to go back a forth a few times with a different sets of source images, maybe adding some image between other two, maybe removing another to reach a better starting point. The key part to pay attention - how many ugly stitches are there in the image. Check every face, the blending algorithms do not recognise faces and sometimes try to stitch one face from two or more images creating very weird effects. They can be fixed in the next step, but it is rather hard manual work, so the fewer such faces are in the blended image, the less work you will have. In some years I've managed to find a combination where all faces were good and in other years I had to manually fix 13-15 faces. Do not try to blend the extra pictures (like with you or with sick people) into the main panorama with Hugin - it will get very confused with the parts of the grass that it is able to see where other people were standing. The next is the final processing in GIMP. Think of it like a large and complex project - do as much as possible in separate layers, save often. Fixing wrongly stitched faces and also putting yourself into the photo are very similar activities in the end. Just the scale and the source differ. For yourself you just cut out yourself (upper torso is enough) from the separate photo. For corrupted face, choose one of two intermediate images that the Hugin created where the face is transformed, but not yet merged (with a different version of itself). In either case crop the photo to roughly the interesting size and put roughly in the right spot as a separate layer on top of the group photo background. Reduce the opacity of the small layer to 30-40% and zoom in to 400%. With that it is much simpler to position the layer with pixel precision. Then all you need to do is add a layer mask to this layer and paint it just right. Basically in layer mask black means transparent and white means non-transparent. So you need to just make everything that is you have white mask and everything that is not you have black mask. And smudge the border a bit with finger tool or blur to make the transition smoother. Easy to say. Hard to do. This is what takes most of the actual work hours in post-processing. You might miss someone. I am sure Phill is just thrilled to see me in the very middle of the Debconf25 final picture .... But do try to fix them all. Use large, sweeping geometric figures to cover up black holes, empty grass fields and other sub-optimal corner features. And then use that newly created free space to put in a large version of the logo of this years conference, decently sized motto and slightly smaller invitation to the next years conference. Do not forget to add a copyright and license statement somewhere in the corner in smaller, but still well readable font. I am using a text like: "Photo by: Full Name, Email: fullemail@debian.org, License: GPLv2+ or CCv3-BY" This ensures that this image may be used in any press coverage (with basic attribution) and also can be included in any GPL-licensed software, if that ever comes up. The same statement is also in the metadata of the image file (see Image-Metadata-Edit metadata in GIMP) along with information that states that this is "Debian Developer Conference Group photo, City, Country, Year". Image->Image properties->Comment is another place where GIMP hides this EXIF information. For ease of use, in addition to a full-resolution image it is also useful to make a lower resolution version that would still fit on a 4K screen at full resolution, so about 3840px wide. Some photo hosting services set other limits for image size as well, so it might be needed to scale the image down below 100Mpix to upload it to Google Photos, for example. Publishing So, it is finally 1AM and the group photo is ready! How do you push it out to people? Well, in all possible ways and places. Again - don't be shy, people do really want to see it. Push it to whatever you use for your shared photos. Push it to Debconf shared git (note that this is GIT-LFS repo, make sure you know how to add content to the LFS specifically). All permanent links to that in GroupPhotosAll wiki. And then send those links to IRC, Signal, Telegram groups, debconf-announce mailing list. Publish it in your blog and push that to Debian Planet. Push it in Threads, Bluesky and Mastodon. Send an email separately to Debconf orga team. And one to Debian Publicity Team so they can put it into the Debian Home Page and push via Debian micronews accounts. And that is about it. Now you can go back to enjoying the rest of the conference. Or running around doing other things that you think need to be done. It's up to you. You did it. This moment will remain with people for a very long time. And you helped. Questions? Feedback? Just ask here or here.

Russ Allbery: Review: The Player of Games

Review: The Player of Games, by Iain M. Banks
Series: Culture #2
Publisher: HarperPrism
Copyright: 1989
Printing: February 1987
ISBN: 0-06-105356-2
Format: Trade paperback
Pages: 295
The Player of Games is political space opera and the second book in the shared Culture setting. As with most Culture books, the reading order is not particularly important. It won the 1989 Locus Award for best science fiction novel and sometimes competes with Use of Weapons as the consensus best Culture novel. This review is a re-read and yet another experiment in how to re-review a book. This time, I decided to write a full second review with substantial spoilers so that I can talk in more detail about the book. If you want to avoid spoilers, or just want to see how my thoughts have evolved from my first reading, see my original review from 2005. Gurgeh plays games. He is probably the best strategy game player in the entirety of the galaxy-spanning Culture. He has written papers on game theory, won innumerable major championships, and is a celebrity in the circle of like-minded aficionados. Gurgeh is also bored and in the middle of the Culture equivalent of a mid-life crisis. As the story opens, he's vaguely unsatisfied and adrift, unenthused by his normal activities, and searching vaguely for something that will break through his ennui. He is caught by surprise by the thrill he gets from a moment's misunderstanding in which an opponent suspects him of cheating, which sets him up to be (apparently) clumsily blackmailed by a deeply unpleasant drone named Mawhrin-Skel. SPOILERS BELOW. If you have not read this book, consider stopping here and instead reading my original no spoiler review. The first hundred pages of The Player of Games is a slow, somewhat plodding introduction to Gurgeh, his social circle, and life in (one part of) the Culture. I remember being fascinated by this part the first time I read this book. It was only the second Culture novel I read and the first set in the Culture proper, so the world-building underlying this odd post-scarcity utopia on a vast intelligent habitat with sentient drones, complex privacy rules, endless cocktail parties, and apparently directionless socialites was intriguingly unlike the other science fiction I was reading at the time. This time through, I have to admit I was less impressed. Gurgeh is not very likable, and his desultory mid-life crisis is a little boring. None of his friends have enough depth to appear as more than side notes, in part because Gurgeh doesn't seem to care enough about any of them to make them interesting to the reader. I've since read seven other Culture novels, so Banks's cocktail parties hold less charm and I was impatient for the real action to begin. These chapters are still important, though, because they establish how utterly average Gurgeh is. He has one unique talent, a deep affinity with and obsession with strategy games, and is otherwise a bit of a depressed narcissist with a few casual relationships, a friend that he barely confides in, and a comfortable and familiar life. He is not in any way a hero or a charismatic figure; he just happens to be exceptionally good at one thing, enough to make him famous among people who care about that one thing and probably unknown to anyone else apart from the occasional idly perused news headline. He is the Culture's equivalent of the world chess champion. The Contact division of the Culture has a problem. The Empire of Azad in the Lesser Magellanic Cloud is a nasty, expansionist culture of the sort that Contact would like to deal with before it causes broader problems. The Culture's normal approaches are thwarted by an unusual organizing principle: The empire is built around and takes its name from the game of Azad, a highly complex strategy game developed over thousands of years. Azad is the civil service exams, means of political and religious dispute resolution, selection mechanism for the emperor, and civic religion. Faced with that oddity, Contact turned to Special Circumstances, the Culture's more aggressive and less restrained way of dealing with tricky problems. Special Circumstances, in turn, needs someone who can learn how to play the game of Azad. They want Gurgeh to take a very long trip. For all of Gurgeh's dissatisfaction, he's not impulsive enough to take a five year journey away from his life and everyone he knows just to play a novel game. Conveniently, Mawhrin-Skel's blackmail resolves this reluctance. The game of Azad requires some suspension of disbelief. Banks provides a few glimpses at the mechanics of the game, but those details are insufficient to reconstruct the rules, and some of the claims made about its properties are improbable at best. The best mental model I could build for it is a strategy or simulation game built around units and territory control, with supplemental side games used to build up resources for the main boards, but it's more of a plot device and a set piece than a world-building invention. The significance of Azad the game is its role in society: The Empire of Azad believes they have constructed a game whose complexity so closely models reality that the skills required for success in the game are precisely the skills required for success in the empire. The Empire of Azad is wrong, and this is one of the core themes of The Player of Games. As with many Culture novels, what Special Circumstances tells Gurgeh is, at best, incomplete. Gurgeh is a refutation of the basis of belief in Azad; this is why it is important thematically that he is an average, somewhat unlikable citizen of the Culture whose only special characteristic is skill at learning and playing games. Azad is the myth of meritocracy given physical form as a game. It provides the anchor of the empire for the same reason that societies on Earth place enormous weight on standardized tests, capitalist success, or public debates. All societies face the problem of selecting good leaders and testing opposing beliefs, and all societies attempt to find some form of shortcut, some set of general principles, tests, or objective metrics used to select the best person via a process that people consider plausible and fair. The game of Azad is a paragon of apparently meritocratic process. No matter who you are or what your background is, if you excel at the game that, in theory, objectively tests your skills, you are given a position of power. In practice, the Empire of Azad is not that naive. Manipulation outside of the game happens, only some players have the opportunity and resources to spend years learning the game at a deep level, and only their dominant sex truly stands a chance in games that matter. But neither is Azad's place in society a fiction. There is corruption around the edges, and a lot of people are filtered out before the games begin, but the highest echelons of society are true believers. The game does decide both rank and policy; Banks is arguing against a strong form of apparently working meritocracy. Gurgeh represents a refutation of this meritocracy through the mechanism that breaks every supposed meritocracy: The map is not and cannot be the territory. Any objective evaluation criteria is necessarily separate from what it is trying to measure, and in that separation there is always an opportunity. Gurgeh has none of the background, training, or mindset expected for a player of Azad because he could not possibly care less about any of the things Azad represents to the Empire. What he has instead is a preternatural skill at games and vast experience with the most intricate strategy games the Culture, a much larger society, has been able to devise. He also has both the patience and the resources to devote himself entirely to learning a game for several years, and past experience in doing that with other games. If Azad represents the civil service exams, Gurgeh is the person who has no interest in ruling but adores memorizing facts and taking tests. The theory behind the exams is that the skills to pass the exam only come with the correct mindset to do the job for which the exam is testing. Gurgeh is an existence proof that this is not always the case. Banks also uses Azad to show another aspect of the failure of meritocracy: A society whose rulers are chosen through a competition takes on the shape of that competition. The Empire of Azad is run by the winners of competitive games, so the empire is a winner-take-all system of dominance and status hierarchy. Here, I think Banks lays the point on a little thick; the empire is an irredeemable hellhole of misogyny, sexual abuse, slavery, genocide, and military colonialism to a degree that is a bit hard to justify solely from the game. There is a beautiful turning point about two-thirds of the way through the book where Gurgeh's face is shoved into just how vile Azad society is and reconsiders his approach to the tournament as a result, and I think it may have been a bit stronger if the morality had been a little less blatant and absolute. To the extent that Gurgeh has political beliefs, he represents a Culture flavor of soft liberalism. He has opinions about acceptable and unacceptable ways to treat people, but he grew up in a utopia and his opinions are mostly theoretical. When he sees just how vile people can be outside of that utopia, he is revolted and appalled and redoubles his efforts to fight that society in the only way he knows how, inside of a game. This part of the book follows the standard, if enjoyable, plot of a flawed but fundamentally decent person discovering a true injustice and becoming enraged at it. In a lot of books, that would have been where the plot stops. Banks is doing something more subtle and more interesting, though. Gurgeh wipes the board with his next challenger, but that soft liberalism eventually proves inadequate. To learn the game of Azad and to play in the tournament, Gurgeh has been wrapping himself in Azad culture and its language, and in that frame of mind he is losing the climactic game of the book. It's only when he is pushed to think in Marain, the native language of the Culture, that he understands what is happening in the game and how to defeat Nicosar, the emperor. This, on the surface, is a bit too close to the strong hypothesis of linguistic relativity to be entirely plausible, but such an objection would miss the point that Banks is making here. Marain is a construct, the product of considerable effort within the Culture to match language to the most nuance and complexity that brains can understand, and it is a language, one of the most social and collective artifacts a society can produce. Gurgeh is a remarkable individual with an impressive talent, but individual skill and achievement can only take him so far. The critical final piece is the support of societal infrastructure intentionally built and maintained to help him make better decisions. Once I noticed that point, I saw it everywhere in the book. The empire repeatedly attempts to subvert or distract Gurgeh with drugs, pleasure, politics, or danger, and at each point there is some critical piece of Culture social infrastructure that blunts the attack. Illicit substances and forbidden vices are less tempting to someone for whom the illicit has been demystified by the Culture's gentler approach to rules and boundaries. Embedded biological mechanisms allow him to divert drugs so that they don't affect him. At first, it's easy to read this as an exercise of self-control, but on this re-read I saw how much behind-the-scenes infrastructure supports Gurgeh's ability to ignore temptation. This social support notably does not take the form of some ideological principle or moral framework. Gurgeh is not a monk or an ascetic, as is obvious from the first third of the book, and he has no political ideology to speak of. He is a flawed person with a streak of danger-seeking and self-aggrandizement, which the Culture exploited to get him involved in Azad. But through a lot of hard work, technological and social, the Culture has given him a robust foundation and a set of mental and biological tools that make him remarkably hard to corrupt. The implication is that if Gurgeh has that support, so does every other member of the Culture. It's neither a religion or an ideology; it's well-maintained infrastructure, complex and nuanced and pragmatic, and composed of innumerable small solutions to specific problems. I think the true climax of this book takes place the night before the final day of the game, in the tower meeting between Gurgeh and Nicosar. Gurgeh has realized that he's already won; there's nothing Nicosar can do to salvage the game. He's also seen that the game represents a cultural conflict and conversation between the Culture and Azad and he's overwhelmed by the beauty of that communication and sadness that the game is about to be over. Gurgeh's true passion is the game. It is doubtless easier for him to be magnanimous because he's winning, but he also loves the structure of the game itself and what two players can create in a sort of collaborative competition. Gurgeh tries to express all of this to Nicosar. It is one of the most centrist liberal moments I've ever read in a novel, the pure essence of "reaching across the aisle" or "disagreeing agreeably." Gurgeh has seen something beautiful, something he's created with Nicosar, a moment of true communication, and he wants to share it. Surely Nicosar sees the same thing; surely now that he sees Gurgeh has won, he can appreciate the board structure, savor the moment, understand the transient beauty of a game that is about to end and how perfectly it captures the meeting of their different cultures. That moment does Gurgeh real credit. It's a rare sign of emotional and spiritual depth in a character who often seems superficial. Nicosar meets this outreach with unhinged, furious contempt. He despises everything Gurgeh represents, everything the Culture is, and the next day he tries to kill Gurgeh on the board of the game. It is a devastating critique of liberal tolerance, all the more so because Gurgeh's attitude and outreach is truly admirable. It is perhaps the most sympathetic moment that Gurgeh has in the entire book, the moment where the reader thinks "oh, I get it, I understand what he really cares about." Gurgeh assumes that Nicosar is not his position or culture, that they have made a moment of connection that transcends all the awful things he previously learned about the empire of Azad. That Nicosar, despite being the emperor of the society that is currently doing so many things Gurgeh finds repulsive, cannot be as bad as his society. And Nicosar considers that outreach to be weak, disgusting, and vile, and does everything that he can to destroy it. One of the oddest twists of our current moment is the obsession that some billionaires have with stories that are moral arguments against exactly what those billionaires are currently doing. The most obvious example is Peter Thiel, who is obsessed with The Lord of the Rings and has devoted his life to becoming Saruman, a character who is notably not one of the protagonists. It's as if something in them recognizes the power of the story, but some deep shame or narcissism or simple aversion allows them to completely ignore what the story means. Elon Musk is obsessed with the Culture novels. He names the SpaceX rockets following Culture Ship naming conventions and has claimed that one of his goals is to bring about a Culture-style utopia. And in 1989, years before anyone had ever heard of him, Banks cast him as the villain of The Player of Games. There is so much of Nicosar in Musk: the superficial charm, the limited brilliance (Nicosar is a very good Azad player), the ambition, the pride, and the vicious, spitting contempt for everything the Culture represents at every level deeper than superficial materialism. And Banks is as clear about his opinion of Nicosar as he is about anything in any Culture novel. One of the oldest fictional answers to what a society does with people like Nicosar is the consequences of hubris. By being unable to accept defeat, by holding a vision of the world so tightly, they become brittle and unstable and bring about their own collapse. In a broad sense, that is what happens in The Player of Games with a bit of pushing from Special Circumstances. By the politics of the game, Nicosar had already won; the results of Gurgeh's earlier games had already been faked, the final game had no political consequences, and everyone who knew its true outcome could be disposed of. Gurgeh's win could have been covered up and ignored. But Nicosar could not endure the thought that he would be beaten by someone like Gurgeh, playing Azad the way that Gurgeh was playing it. Gurgeh had to be destroyed on the board of the game; Nicosar's pride did not allow any other outcome, even if it meant Nicosar's death. However, Special Circumstances didn't let hubris be the end of the story. In the climax of the book, the drone protecting Gurgeh also makes sure that Nicosar dies. There is a fig leaf of plausible deniability, but it's so obvious that even the unobservant Gurgeh sees through it immediately. It's hard to escape the feeling that was Banks's answer to what to do with people like Nicosar: They cannot live within society, because they will not live peacefully within society. I enjoyed The Player of Games as much this time through as I did the first time, but for entirely different reasons. In my first read, I focused on the world-building of the Culture, the political machinations, and the concept of games as conversations between the players. This time, I was struck by the political commentary just below the surface. Special Circumstances wanted to resolve the problem of the Empire of Azad without a military conflict and occupation that would be long, brutal, expensive, and demoralizing. They found an answer that relied on the diversity of the Culture. A vast, utopian civilization in which people can pursue whatever interests make them happy produces innumerable microspecialized oddities, people with astonishing talents in some small field that only a tiny fraction of people care about. It produces, in other words, innumerable keys for locks that you may never encounter, but which are invaluable if you happen to stumble across that lock. Gurgeh is not a hero. He is not a paragon of moral virtue, or even a charming charismatic, He is an entirely average member of an extraordinary society, the beneficiary of thousands of years of concerted effort at producing a robust, flexible foundation on which to raise robust, flexible citizens with a shared sense of basic morality. Those people, by themselves, do not solve all of life's problems; the structure of Special Circumstances and its willingness to bend rules in order to maintain them is the tension and deus ex machina in all of the Culture novels. But much of the strength of Special Circumstances is that it has an entire civilization of people like Gurgeh to draw upon when it needs them. It has those people because the Culture comprehensively rejects competitive meritocracy, something that some readers of the Culture novels appear incapable of comprehending. Rating: 9 out of 10

3 July 2026

Matthew Garrett: Securing agentic identity

As is the case for many people working in the security industry, the last few months of my life have been focused on dealing with people wanting to use LLMs everywhere. From an enterprise security perspective that s not an inherent problem - what s more of a problem is that people want those agents to have access to resources like their calendar and email and so on, and now we have somewhat non-deterministic agents that seem very enthusiastic to achieve what you asked whether that s a good idea or not, and we re combining this with credentials that give them access to sensitive data, and leaving those credentials on disk where they can be committed into git repos or exfiltrated to some other service to make use of them on the agent s behalf or well just any other number of things, at which point your CEO s email is suddenly readable by everyone and you re having a bad day. As I mentioned in my last post, pretty much every strong mechanism for keeping credentials in place is just not supported in the wider world. We can imagine a universe where agents use hardware (or at least hypervisor) backed certificates to obtain credentials and any that end up leaking are worthless as a result. But, sadly, that s not an option for most people using existing identity providers. The state of the art is that you use the device code flow and a human authenticates and the token ends up back inside the agent environment and then it proceeds to do whatever it wants with it and you just hope that you wake up the next morning without an awful infoleak occurring. (An aside: I do not like the device code flow as used in enterprise environments, and I never will. The identity provider doesn t have a real opportuity to inspect the security posture of the system asking for the token, and as a result some identity providers will restrict tokens that are issued in this way. The common alternative of doing stuff using a more standard flow and having a redirect URI pointing at localhost works fine for local systems and is a pain for remote ones, even if you can commit crimes with SSH forwarding. I m going to suggest something that I think is better, and you are free to disagree) I m not in a position to get every identity provider and service provider to change their security posture, so I m somewhat stuck in terms of the tokens they re willing to issue me - largely either JWTs or opaque access tokens, with no support for any mechanism of binding that token to an instance. The token that s going to have to be provided to the remote service is something I have little influence over. But that doesn t mean I can t influence the token that lands inside the agent s environment. I can issue a placeholder token to the agent, and force it to communicate via a proxy that swaps out the placeholder for the real thing. The worst the agent can do is exfiltrate the placeholder token, and as long as malicious actors don t have access to that proxy, it doesn t matter - nobody else can do anything with the placeholder. This isn t a terribly novel insight, and it seems like almost everybody has reinvented this on their own. But a lot of these implementations involve you somehow obtaining the real token in advance and then pasting that into something that generates a placeholder that you provide to your agent environment somehow, and it s all a bit clunky and awkward, and it also means that you need to deal with something that keeps track of the mapping between placeholders and real tokens and oh no we ve just invented a secret store, and if you want this to work at scale and reliably you re just invented a high availability distributed secret store, and a lot of people who ve read that are now shaking their heads and reaching for gin. Can we simplify this, and improve security at the same time? I think we can! Remember when I said as long as malicious actors don t have access to that proxy, it doesn t matter ? What if they do? What if they compromise one machine inside your environment and are then able to email a bunch of employees and convince their agents to send more tokens back to them and then delete the email before a human reads it? Now you have someone inside the wall with access to those tokens, and presumably with access to the proxy, and now they can be anyone whose agent was gullible enough to think sending them a token was a good idea. This isn t good! So, I thought for a while, and I came up with a new idea. We can have a broker service that obtains credentials for us. We can run that centrally, away from the agents. A client in an agentic environment can request a token, and that can result in a URL being generated and the user being directed to open a URL in a browser and authenticate. When the user authenticates, the authentication flow redirects the confirmation back via the broker, and the broker obtains the real auth token. The obvious thing to do now would be to return the auth token to the client in the agentic environment, but we don t do that. Instead, we mint a new JWT, and add a new claim - one that contains an encrypted copy of the token. In the process we can copy over all the original claims, because those aren t secret - and now even if the client inspects the token to figure out what access it has, it ll get a correct answer. We sign the new token with our own signing key, and pass that back to the client. The client now has a legitimate JWT that is utterly useless, because the signature isn t trusted by anyone other than us. How does it use it? It makes an API request via a proxy, including the new token in the Authorization: header. The proxy verifies the signature on the token, and then decrypts the original token and swaps out the fake token for the real one. The remote API sees what it expects, and everyone is happy. There s never a real token in the agentic environment, but also we don t need to store anyting anywhere. The only state is the encryption keys, and those can be injected into the environment at startup. You need to scale? Just start more of these processes. You need to support multiple availability zones? Just start more of these processes in different places. No persistent data is ever held in the broker or the proxy. You don t need to care about distributed databases or secret stores. This felt wonderfully elegant and I felt smug about coming up with a better idea, and then I went to a bar earlier this week and sat down to read RFC 8705 and the guy next to me saw that over my shoulder and asked what I was reading and I explained why I was interested and we talked about agentic identity and then he mentioned that fly.io had something that sounded very similar and I read that and gosh yes it is very similar, so damn you fly.io for stealing my ideas 3 years before I even had them. Anyway. Now I need to do better. Remember that there s still a risk around anyone who has access to the proxy having access to the encrypted keys? We can remove that risk as well. It s not uncommon for agentic environments to have an identity issued via something like SPIFFE, at which point they have a client certificate. You can probably guess where I m going with this. If we require that an agent present a client cert to the broker when requesting a token, we can embed a representation of that client cert into the token we mint. The proxy can then require mTLS for the client connection, and can verify that the presented certificate matches the one represented in the token. If it does then whoever s using the token has access to the private key associated with the environment it was issued to. If we then ensure that the private keys backing these certificates are either hardware or hypervisor backed, and as such tied to a specific instance, we now have a high degree of confidence that the token can only be used in its intended environment. Even if our identity provider doesn t support RFC 8705, we can. This is fairly straightforward where you re using a platform where your identity provider is also the environment that s consuming your tokens, and more annoying for third parties. The broker potentially needs some amount of third party vendor knowledge to make that work for everyone. This is even more the case where login isn t via your identity provider (thanks, github), but none of this is insurmountable - just annoying. And where vendors issue opaque tokens rather than JWTs, this still isn t a problem; we can just mint a new JWT that includes the opaque token as an encrypted claim, and include the same certificate binding. The opaque token ends up being the thing that s presented to the third party, but only after we ve verified the mTLS binding. In an ideal world none of this would be necessary - someone would spin up a new agentic environment, a user would prove their identity, and a certificate embodying that identity would be issued to the environment with a private key that can t be exfiltrated. That certificate would be sufficient to obtain new certificates associated with the same private key, and we could still bind that into mTLS identity. This would be much simpler, but browsers don t support it, so it s not likely to happen any time soon. Anyway. Even if we can t have the best thing, we can do better than we are at the moment, and also it would be lovely if we could standardise on this rather than have everyone build their own thing. The end.

2 July 2026

Valhalla's Things: A Pair of Hair Towel Wraps

Posted on July 2, 2026
Tags: madeof:atoms, craft:sewing, FreeSoftWear
Two trapezoid shaped hoods made out of off-white towels: one is still looking new, while the other one has been bleached and roughened by having been washed many times. Many months ago I had been ordering some furniture from IKEA1 and on one of those orders I got tempted by a hair towel wrap: it mostly worked as an idea, but it was too short for my hair. On the other hand, I had two old towels I wasn t using, and a recently unpacked sewing machine. A towel cut in two trapezoid halves with a STJ RNBUSKE laid on top of it: the IKEA wrap is a bit less than 10 cm less deep, and at least 30 cm shorter, and is also triangular rather than a trapezoid. I didn t plan too much, I just put the STJ RNBUSKE over the towel, cut, realized that the two pieces didn t fit with right sides together, cut the second towel (I had planned to make two wraps, anyway, so it wasn t a big deal), and started sewing by machine in what seemed like a reasonable procedure, taking notes and pictures. A towel, with its original care label, that has been cut in a trapezoid shape and reassembled into a hood shape with a long triangular tail. The machine sewn finishing is still neat and pristine. The result was pretty good, and I started using it every time I washed my hair, but then I started to entertain the idea of shooting myself sewing the second one by hand for a video, but never found the time to actually doing it, and the pieces remained in the Pile for months, and months, and way more than a year. The head of a woman with a turban-like thing on the head, covering all of the hair except for a tiny bit at the center front. Until one day I bought a meter of cotton cheesecloth (mostly because it was almost cheaper than buying a sample) and it felt like a good material to make a nicely looking head wrapper, to keep my hair out of the way when needed. A woman in a bathrobe with her head tilted downwards, covered by a towel thing that lies on the back of the head and has a long tail hanging on the front, in the process of being wrapped around the hairs and then brought over the top and back. A couple months later, it was finally time to bring this project to the top of the list, and even if I was sewing two by hand it went pretty quickly: we had a weekend when it was too hot to do anything else, and by the end of it the wraps were done. All that remained was finish writing the instructions for my FreeSoftWear patterns website <https://sewing-patterns.trueelena.org/contemporary_unisex/headwear/hair_towel_wrap/index.html>>, and having some pictures taken, and this project was done. And now, on to documenting a few more things I ve done lately, and to start working on the other projects I have added to the queue in the meantime.

  1. small things. Like, you know, a kitchen :D

19 June 2026

Wouter Verhelst: Agentic coding and Free Software

Through work, I have paid license to windsurf (recently renamed to "devin"), an application for LLM-based (aka, "Agentic") development. I hadn't been using it that much, but in an effort to more clearly understand how this whole AI development thing works, I decided to give it a closer look recently. My conclusions: In its current form, this whole LLM wave is problematic for multiple reasons. But ignoring that, and looking at the technology only, I can say that:

Problems Lest someone (incorrectly) assume that I am arguing in favour of the current state of affairs with regards to LLMs, let me state this first. The way LLMs are built today is highly parasitic. Websites are downloaded in whole, at unsustainable rates, regardless of the consent of the people who made the original content. The result is predictable: servers get overloaded, server administrators attempt to implement various mitigations. Some of these mitigations work; some do, for a while; some are entirely useless. In actual fact, the mitigations are an arms race -- if too many people implement the same mitigation, then the people who try to build yet another LLM so they can extract rent will just try to work around the mitigation, eventually they will succeed, and you'll just have to come up with another mitigation. It's a bit like spam; you introduce regex-based spam filters, they introduce spelling mistakes, you introduce bayesian filters, they add a large batch of markov chain-generated semi-nonsense words made invisible by markup, you add filters to block emails with such markup, they move the text into an image. We have working mitigations today, but eventually we'll run out of ideas. LLMs glob up everything they can while ignoring the license of the source material. The people who push those LLMs claim that pushing the source material through the machine learning algorithms makes the output of the algorithm distinct enough from the source material that the license no longer applies; I'm not so sure that this is true. I guess the New York Times v OpenAI lawsuit will teach us some of the answer to that question here, but even so the ethical questions about "is it OK to bring down another server just so we can download the internet for another for-pay LLM" are still open. And regardless of what the law states, my opinion on "you're using my copyleft code to generate code under a different license" is not something you might like if you agree with the rent seekers' opinion on the subject. That all being said and true, the technology works. You can have a "conversation" with an LLM that resembles a human one. If you pass it some data, you can use plain english to ask it questions about that data, which is a lot easier than to ask it about that in a formal way. You can request it to generate some code, and it will generate something that looks like what you need and that will be mostly correct for like 95% of the time. Now, yes, 95% of the time is not 100% of the time, and no, you can't ask it to "write me a piece of software that implements this 300-page requirements document and get back to me when you're done", because it will fail, and you won't know where it has failed, and you'll take it into production and expect everything to be fine because it won't and this one minor logic bug will cause half your servers to spin and consume credits with your infrastructure provider with nothing to show for it. But that doesn't mean you can't use an LLM to build a large piece of software. It just means you have to understand the LLMs limitations and strenghts, and use them correctly. Here's what an LLM is good at:
  • Generating plausible text
  • Interpreting text to figure out what a plausible meaning or summary of that text is
  • Giving vague indications as to what the probable context of a given body of text is.
It turns out that that's enough to use the LLM to build a reliable piece of software, provided you do it right.

Paradigm shift An LLM can generate text by the truckful. The generated text could be code. Given a good enough LLM, the generated text might even run and do something useful. You can try to blindly run the code, and if it doesn't run correctly, you can paste the error message to the LLM, and it can tell you what went wrong and how you could possibly fix it. This creates a feedback loop: you ask it for an amount of code, you run the code, you receive an error, you tell it that the code is problematic and give it the error message, it makes changes to the code, now you have something that at least no longer fails at startup. If you ask it to add tests to make sure that your code acts as per your specification, now you get an error if and when the code doesn't act as per your specification. Or, well, at least not as per the part of the specification that was correctly turned into a unit test by the LLM. LLMs have a context window, so if the error message is pasted in the same conversation as where the code was generated, it is able to reuse the earlier prompts to refine how it should interpret the error message that you received. You can't really paste the source code of an entire application into the prompt of your LLM, that would quickly overrun its context window. But LLMs also allow you to provide some form of background information -- a document, say -- on which you ask it to reason. It will interpret that document, but doing so uses less of the LLMs context window. So providing the LLM with your application's source code as background information can help it understand better how your code interacts. This is especially helpful if you only provide the LLM the background information relevant to the actual question. So now if you are able to:
  • Create background context with your application's source code
  • Have the LLM generate a first draft of your requested change, plus the tests to make sure it works
  • Compile (if applicable) the generated code (and tests) and run said tests
  • Return any error messages to the LLM with a request to correct the error
Then the combination of "getting it 95% right off the bat" and the above feedback loop means you can generate syntactically correct code, that probably does what you need, in minutes. I say "probably" for a reason. There are going to be cases where you specify a request without a number of details (because they are implied), and the LLM will get most of those details right but just not implement the one bit because it's an automaton and it doesn't think. Or you will ask it to make sure that two bits of the application look exactly the same, without specifying that they must act the same, now and in the future, and it will just generate the same block of code twice and then in a future change it will change one but not the other. But if you review the changes, and you have experience as a programmer, you will be able to spot most cases where the LLM got it wrong. And so it's possible, if not necessarily easy at first, to use an LLM to generate mostly correct code. There are certain places where "mostly correct" code is not desireable. But equally, there are also cases where, "mostly correct" is good enough. After all, most of the software you run today -- the bits of it that weren't, yet, generated by an LLM -- is only "mostly correct", too, because to err is human and we all make mistakes. If not, there wouldn't be any CVEs and your software would never do anything wrong. Now, doing the feedback loop described above is certainly something you could do manually. You could open an account on one of the LLM websites, upload the source code of your application, ask it to generate some new feature, download the newly generated feature, run it, and then copy/paste any error messages back into the LLM. But that's a lot of manual work of the type that computers are pretty good at. So that's what the "windsurf" tool helps you with: you run it inside your IDE -- either a VSCode-based tool that you download from their website which comes with their product preinstalled, or a separate JetBrains plugin that you can install. You can then open your entire relevant codebase in a workspace in your IDE. You then ask the LLM, through the IDE, to generate a new feature in your codebase, and to also generate the test while it's at it. It will use a mixture of LLM interpretation and non-LLM functionality to scoop out the relevant bits of your codebase to send to the LLM as background information, will send it your prompt, will download the generated code and patch or create files, will compile (if required) and run the newly generated code and tests, and will refine the generated code if the tests produce any errors. All mostly automatic; by default, running anything requires explicit confirmation. You can turn that off completely (probably not a good idea), or you can give it a whitelist of things that you don't want to confirm (perhaps OK), and the tool also passes standing instructions to the LLM to never generate any command that deletes a file (which, like with any LLM, can be overridden, but it requires you to be very stubborn and to use more credits than you'd probably like). All this put together means you can build something without writing any piece of code, provided you do it right.

A technically positive evolution Don't go and say, "here's a 300-page document, read it and write whatever the document says". It will get it wrong, it will write a massive test suite that it will only run at the end, it will choke itself up trying to interpret the massive amount of failures it encounters, it will fill up its context window and it will start to forget some of the requirements. That won't work. But what you can do -- what I did, in fact -- is this. First, create an empty workspace. Don't put any code in it. Then, tell the LLM to generate a backend framework using technology X and a frontend framework using technology Y that initially only says "hello, world". Also add tests to it, and run the tests. It will do that. You'll not get much, but it will work. Then, ask it to add some UI elements. A login page, perhaps. A navigation bar. Small things. Most of it doesn't have to be functional -- but tests must be there for the bits that are, and have it run the tests and evaluate the results. Rinse, repeat, until you have a working application. Importantly, in between the steps, you should also run the application yourself and see if the change was implemented correctly. Sometimes it won't be. Sometimes there will be a subtle bug -- I at one point had a the application hang after a few minutes. Sometimes you tell it that there's a subtle bug, and it will discover it more quickly than you could, and it will fix it, and in implementing the fix it will uncover another bug, and then you have to fix that one -- the fix it came up with for the hang was to move something to an async process on the server, which caused the application to start spinning while trying to create hundreds of async jobs (this is when I realized that the hang was a deadlock due to some part of the codebase doing something that indirectly triggered itself). Sometimes it will try to fix the bug you tell it about, and you'll see that it's going off on a tangent that has nothing to do with what you're seeing. It's important to keep an eye on what it's doing, so you can guide it back on track when that happens -- when I told it about the hang, it started investigating the part of the code which sends out emails, thinking that it could hang while waiting for sendmail to finish, but the hang was happening when the application was idle, not when it was sending out emails, and only when I told it about it happening when it was idle did it find the deadlock. So it's not a fully automatic process, and it needs to be guided by someone who knows what they're doing. But if that is the case, you can come up with something that works. I spent evenings and breaks for about a week, and I managed to create a working application which, had I written it by hand, would have taken me a few months of full-time work to come up with. And I now have a side project, fully complete and working, that I had been thinking about doing for more than a decade, but never got around to actually doing, because of all the work that would be involved and I just didn't see myself having the time for. It's not perfect code. But it's mostly good enough, and it will perform the job it needs to. And it looks far slicker than most of the side projects I've done in the past, because in the past I would prioritize between implementing new features or making something look slick, and I would decide that the new feature was more important because it's only for me and there's only me and nobody cares if it looks good or not and I don't have three weeks to come up with something that looks better. But here, I found myself sometimes spending 10 minutes writing a prompt with instructions on making things look better. Because what's 10 minutes when you just spent an hour writing down and refining specifications for functionality and tests? There are a number of other things in which an LLM can help a programmer. For instance. I received a bug report recently in a project I'm paid to maintain that I couldn't make heads or tails of. I opened the source code in my windsurf IDE, pasted the bug report in the prompt, and then requested the tool to analyze the source code and the associated logs and tell me how the described behavior could be happening. It turned out that I had overlooked something, but with the help of the tool, I found the bug in minutes. I was trying to understand a particular part of a large codebase that I didn't really grasp very well. I loaded the codebase in the tool, and asked it to explain to me how a particular action is performed by the code. I requested specific functions and line numbers. I now have a far better understanding of how the code works, and will be able to write that patch that I've been wanting to write for years -- without using the LLM. I have been struggling for, literally, years with understanding why another tool that I maintain was misbehaving in a particular way but only in Firefox. I opened the codebase in Firefox, explained the buggy behavior in plain English, and asked it to explain how this could be happening. It picked up some obscure corner case behavior of ffmpeg and mp4 containers that I was not aware of and that perfectly explained why things were misbehaving in the way that they were. At the same time, there are limitations. Giving an LLM a codebase that was originally generated by an LLM (either the same one or another one) seems to work well. Giving it a codebase that was written by a human and expecting it to correctly update it seems to be more error-prone. I did one or two of those as a trial, and it is more problematic than anything. An LLM is also not intelligent, notwithstanding the popular term of "Artificial Intelligence". On multiple occasions, I've asked it to write a test case for some code that was not set up to do so; and rather than suggesting a refactor is required, it would instead copy the code that needed to be tested and then test the copy, rather than the original. The tool has made multiple similar errors. I have sometimes people describe agentic coding as "similar to interacting with junior programmers", but that is not the case. A junior programmer will either fill in the gaps in your specifications, or ask for clarification when something seems off. The LLM will not do that; it will do what you ask, exactly that and nothing more. If you missed a corner case in your specification, then all bets are off. I remember learning about programming language generations in college. A first-generation language is "machine code", a second-generation language is "assembler", a third-generation language is any high-level language such as C, Perl, or Pascal. I've forgotten what set a 3rd-generation language apart from a 4th-generation language. But I remember the definition they gave me for a 5th-generation language: "you tell the computer what to do, and it will do it". At the time, I thought it was ridiculous. Nobody could ever write something like that. But it's here. And it's a threat to free software.

A threat to free software? Yes. There is the obvious part where most of the well-known LLMs are non-free software. I mean, there are some "open source" LLM models. The windsurf tool that I used doesn't allow you to use them (directly), but they're there. There are also open source applications that implement what the windsurf editor does. So it's definitely possible to work like this without resorting to non-free software and non-free services, even though the non-free LLMs might be a bit ahead of the curve of the free ones. But that's not what I mean. And there is also the obvious thing which I mentioned earlier in this post, which is that the people who try to build LLMs are doing it in unethical, disgusting ways, causing downtimes and disregarding licenses for whatever they can get their grubby hands on. Ideally we wouldn't be in that situation, and ideally this wouldn't be a problem, but we are where we are. And there's the obvious thing where the OSI sold itself out and declared that a machine learning program can be open source even when the very things it was built from -- the training data -- is not available. That's a major issue that the free software community needs to fight against, but there's not really anything that that is a threat to free software. You just build your own, free software, LLM, and you're done. The actual threat is in funding and developer support. Most large businesses do not care about free-as-in-freedom software. They like the free-as-in-beer part, and they appreciate that the free-as-in-freedom bits can make the software more customizable. They are (mostly) happy to do sponsorships of the free-as-in-freedom projects that they use if that means their free-as-in-beer usage of the software gets improved. But why would you care about all that when you can just generate the code you need, rather than interacting with an open source community that may or may not care about your business's interests?

Where to go from here Although I think the moral and environmental issues with LLMs are real and problematic, given the experiments I did I am not convinced that the concept of interacting with a computer system in natural language and to use it to generate code is necessarily deficient. There are pitfalls, but they can be managed. It is possible to use such a system to create throwaway, proof-of-concept type "good enough" code bases. It can be used to interpret code bases and to understand bug reports. I believe that the major issue with LLMs has to do with that saying about hammers and nails:
If all you have is a hammer, then everything looks like a nail.
LLMs are an outgrowth of machine learning, pushed by large corporations. These large corporations have a lot of money. If all you have is money, then every problem can be fixed by throwing more money at it. The initial language models were promising but not (yet) good enough, and it seemed that one way in which they could be improved was to increase the scale of the statistics: throw more hardware (and thus money) at it, and rather than improving the efficiency of the models, just scale up. Scaling up is something that megacorporations are very good at. It's only a money problem, after all. Does that mean that "scaling up" is the only way to improve the models, though? I'm not convinced. Some hardware, such as most modern Apple and Samsung devices, ship with accelerator hardware for machine learning algorithms. There are some models that are small enough to be able to run on these devices. I don't see why it should not be possible to create a small(er) language model that can do some useful part of the above-described use cases; if not locally, then at least on a server that one can run on-prem rather than requiring that you pay rent to one of the LLM companies. The Software Freedom Conservancy has published an aspirational statement on machine learning-assisted programming that, I think, gets a lot right. It's not quite a definition, but it's something to keep in mind. Perhaps that's the way forward? More questions than answers at this point, anyway.

Junichi Uekawa: looking for last.

looking for last. I realized it's gone. what's my replacement?

18 June 2026

Mike Gabriel: Commenting on the recent Ubuntu Touch review done by @SwitchandClickOfficial on Youtube

There has been a video blog post recently published with a review of Ubuntu Touch as an option to opt out of the Android world: https://www.youtube.com/watch?v=wTK6TS3pXgc Thanks to @SwitchandClick for spending time on this and publishing that video. Much appreciated. Many Issues amended in upcoming 24.04-2.0 Release When I watched that video referenced above, I continuously thought: ah... this is fixed in the next major release of Ubuntu Touch, or: ah... this is a known issue that we have on the roadmap..., or: ah... this is done in this ways by design (so it's a feature or basic functionality)... Let me just state, that most of the criticized aspects will be resolved in upcoming Ubuntu Touch release 24.04-2.0 (the tests in that video blog post have been run on Ubuntu Touch 24.04-1.x): The full feature preview of the 24.04-2.0 release can be found here: https://ubports.com/blog/ubports-news-1/ubuntu-touch-24-04-2-0-beta-is-n... Ubuntu Touch App Ecosystem The app ecosystem of Ubuntu Touch is quite specific, because many apps in Ubuntu Touch have been explicitly developed for Ubuntu Touch using a widget toolkit called Lomiri.Components. However, in Ubuntu Touch we also encourage developers to provide apps written with other convergent-capable toolkits, such as QQC2-based apps or Kirigami-based apps. One reason for the very different app ecosystem in Ubuntu Touch is that many service providers don't have Ubuntu Touch on their radar when investing in app development for their services. Some Ubuntu Touch App Developers work around this by either implementing unofficial client apps for web services (e.g. the Flow app for Deezer by Sander Klootwijk), others provide the web service via implementing a web app (will not work when offline, but at least will show up as an app in the launcher). The overall solution for making Open-Store.io more familiar to users who migrate from Android is that commercial service providers start honouring digital sovereignty and start providing apps for Linux. Not just for the Linux desktop, but also for mobile Linux platforms. This dual use case can easily achieved with an app development that bears convergence in mind. App Ecosystems are also a Matter of Perspective And one more minor note: whenever I open an Android appstore or can peak over someone's shoulder using an iOS device: I always wonder: what are all these apps about??? Never heard about them. So, familiarity really depends on perspective. And perspective depends on what you are used to. Change what you do and your perspective will follow. Ubuntu Touch's root filesystem (rootfs) is Immutable Only thing from that video blog post that we haven't fixed and won't do so in the midterm future is apt-get not working on the command line. The reason for this is: the Ubuntu Touch root file system is an immutable file system and thus shall not be changed via apt-get & friends by ordinary users. There are various discussions ongoing such as dpkg-divert'ing apt-get to a wrapper shell script that spits out an error message if rootfs is mounted read-only and someone tries to install packages the Debian/Ubuntu way. Other approaches are to mount some RAM disk over the rootfs, so apt-get can be used at runtime but changes to the system get reset at reboot. However, it is possible to mount the root filesystem read-write and test newer package versions (as UT core developers do regularly, in fact). If you tinker with this, it is recommended to reflash your device (don't wipe user data, when you reflash!) from time to time, because adding packages or package upgrades to your rootfs may over time corrupt the integrity of the rootfs. One reason for apt-get breaking the rootfs and thus your Ubuntu Touch development device is that the upgrade process of the rootfs image is incremental, so update tarballs sometimes contain only those parts that got changed between this and your previous upgrade (sometimes, upgrades contain a complete rootf image, depending on the interval between upgrades). If files from an incremental update tarball mix into a rootfs that got tinkered with via apt-get, you really end up on your own. Re-flashing will grab the complete rootfs tarball and wipe the whole rootfs and reinstall a fresh version of the newest rootfs image. Developers also do this in regular intervals to ensure their test device is clean again before running more/other tests.

14 June 2026

Matthias Klumpp: Introducing pkgcli: A nicer command-line interface for PackageKit

For almost two decades, the PackageKit package management abstraction layer has shipped with pkcon as its command-line client. pkcon does its job, but it was always kind of a testing front-end for the PackageKit daemon rather than a tool designed for everyday use. The focus has instead been on the GUI tools, automatic system updates, GUI application managers and other front-ends. Its command names mirror the D-Bus API almost one-to-one (get-details, get-updates, get-depends), output is very plain, and there is no machine-readable mode for scripting. Most importantly though, there has been no development on it at all for almost a decade, so pkcon was stuck in its rudimentary state from that era.

Since a lot of changes will be coming to PackageKit, and testing the daemon and working with it from the command-line was not very pleasant anymore in 2025/2026, I decided to modernize the tool as part of my work as fellow for the Sovereign Tech Agency last year. pkgcli is the new command-line client for PackageKit. It is built from the ground up to be pleasant to use interactively and easy to drive from scripts.

Why a new tool?

Of course, instead of introducing a new tool, I could have just expanded pkcon instead. The problem with that approach is that the pkcon utility has been around for so long and its command-line API had ossified so much, that rather than changing it and potentially breaking a lot of scripts relying on its quirks, I decided to introduce a new tool instead. pkcon can still be optionally compiled for people who need it in their scripts and workflows.

The goals for pkgcli, and the features it now has are:

  • Human-friendly command names. Verbs that read the way you d describe the task, instead of mirroring the D-Bus API 1:1: show, search, list-updates, what-provides, instead of get-details and friends.
  • Readable, colored output by default (still respecting NO_COLOR and degrading gracefully).
  • A real scripting mode. A global --json flag emits JSONL instead of fully human-readable output when possible, to make it easier to use the tool for scripting purposes.
  • Sensible defaults. A few defaults have been changed, such as the metadata cache-age, or automatic cleanup of unused dependencies being enabled by default. This is more in line with current defaults by other tools and frontends. We also print package information in a slightly different, more readable way.
  • Better handling of internationalized text. Text should now align properly in the terminal window, and we should no longer have completely chaotic text output on non-English locales (especially Chinese/Japanese).

Why not pkgctl?

Originally, this tool was called pkgctl, to match other common cross-distro tool names. However, that name was already taken by an Arch-specific distro development tool. When this issue was raised, we decided to just rename our tool to pkgcli with the next release, to avoid the name clash on Arch Linux.

Examples!

Here are some examples on how to use the new tool (some of which include the abridged output pkgcli prints).

Search for anything containing the string editor in name or description, then look at the details of one result:

$ pkgcli search editor
Querying                  [ ] 100%
  ace-of-penguins 1.5~rc2-7.amd64 [debian-testing-main]
  acorn-fdisk 3.0.6-14.amd64 [debian-testing-main]
  ardour 1:9.2.0+ds-1.amd64 [debian-testing-main]
  audacity 3.7.7+dfsg-1.amd64 [manual:debian-testing-main]
  audacity-data 3.7.7+dfsg-1.all [auto:debian-testing-main]
  augeas-tools 1.14.1-1.1.amd64 [debian-testing-main]
  emacs 1:30.2+1-3.all [debian-testing-main]
  gedit 48.1-9+b1.amd64 [debian-testing-main]
  gedit-common 48.1-9.all [debian-testing-main]
  gedit-dev 48.1-9+b1.amd64 [debian-testing-main]
[...]
$ pkgcli show nano
Package: nano
Version: 9.0-1
Summary: small, friendly text editor inspired by Pico
Description: GNU nano is an easy-to-use text editor originally designed as
 a replacement for Pico, the ncurses-based editor from the non-free mailer
 package Pine.
[...]
URL: https://www.nano-editor.org/
Group: publishing
Installed Size: 2.9 MB
Download Size: 646.0 KB

Search only within package names rather than descriptions:

$ pkgcli search name python3

Check for updates. refresh updates the metadata, then list-updates reports what s available:

$ pkgcli refresh && pkgcli list-updates
Loading cache            [ ] 100%
  cme 1.048-1.all [debian-testing-main]
  gir1.2-gdm-1.0 50.1-2.amd64 [debian-testing-main]
  imagemagick 8:7.1.2.24+dfsg1-1.amd64 [debian-testing-main]
  imagemagick-7-common 8:7.1.2.24+dfsg1-1.all [debian-testing-main]
  imagemagick-7.q16 8:7.1.2.24+dfsg1-1.amd64 [debian-testing-main]
  libdlrestrictions1 0.22.0.amd64 [debian-testing-main]
  libfftw3-bin 3.3.11-1.amd64 [debian-testing-main]
  libfftw3-dev 3.3.11-1.amd64 [debian-testing-main]

Explore relationships between packages:

$ pkgcli list-depends inkscape  # list what inkscape depends on
$ pkgcli list-requiring libappstream5  # list what requires libappstream5

Find the package that provides a capability, here the AV1 GStreamer decoder:

$ pkgcli what-provides "gstreamer1(decoder-video/x-av1)"
  gstreamer1.0-plugins-bad 1.28.3-1.amd64 [auto:debian-testing-main]

You can also have JSON output for most commands! Attach --json to any query and pipe the result straight into jq. Each line is a self-contained JSON object:

$ pkgcli --json list-updates   jq -r '.name'
cme
gir1.2-gdm-1.0
imagemagick
imagemagick-7-common
imagemagick-7.q16
libdlrestrictions1
libfftw3-bin
libfftw3-dev
libfftw3-double3

Try it

pkgcli is built by default alongside the rest of PackageKit since PackageKit 1.3.4. If your distribution ships a recent enough PackageKit, it should already be on your PATH. You can read its man page man pkgcli for more information. Feedback, bug reports, and patches are very welcome.

Next.