<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
    <title>The Log</title>
    <subtitle>By Beshr Kayali Reinholdsson</subtitle>
    <link rel="self" type="application/atom+xml" href="https://log.beshr.com/atom.xml"/>
    <link rel="alternate" type="text/html" href="https://log.beshr.com"/>
    <generator uri="https://www.getzola.org/">Zola</generator>
    <updated>2026-04-03T00:00:00+00:00</updated>
    <id>https://log.beshr.com/atom.xml</id>
    <entry xml:lang="en">
        <title>Writing a CHIP-8 Emulator from Spec</title>
        <published>2026-04-03T00:00:00+00:00</published>
        <updated>2026-04-03T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Beshr Kayali Reinholdsson
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://log.beshr.com/chip8-emulator-from-spec/"/>
        <id>https://log.beshr.com/chip8-emulator-from-spec/</id>
        
        <content type="html" xml:base="https://log.beshr.com/chip8-emulator-from-spec/">&lt;p&gt;I&#x27;ve been working on &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;ossature&#x2F;ossature&quot;&gt;Ossature&lt;&#x2F;a&gt;, a spec-driven harness for LLM-based code generation. You write specifications describing what your software should do, and a build system generates code from them one task at a time, with validation and verification at each step. I wrote more about it on the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;ossature.dev&#x2F;blog&#x2F;introducing-ossature&#x2F;&quot;&gt;Ossature blog&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;To test it on something non-trivial I decided to write a &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;CHIP-8&quot;&gt;CHIP-8&lt;&#x2F;a&gt; emulator. CHIP-8 seems simple on the surface but has enough subtle behavior to actually test whether generated code holds together. There are known quirks where different interpreters disagree, and tricky state management that trips up both humans and LLMs. The project is called &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;beshrkayali&#x2F;chomp8&quot;&gt;chomp8&lt;&#x2F;a&gt;. It&#x27;s generated with Ossature in Rust, uses SDL2 for display and audio, and the entire codebase came from three spec files.&lt;&#x2F;p&gt;
&lt;figure class=&quot;fullwidth&quot;&gt;
  &lt;video controls loop muted playsinline style=&quot;width: 100%&quot;&gt;
    &lt;source src=&quot;chomp8.mp4&quot; type=&quot;video&#x2F;mp4&quot;&gt;
  &lt;&#x2F;video&gt;
&lt;&#x2F;figure&gt;
&lt;p&gt;I split the project into three specs. &lt;strong&gt;CORE&lt;&#x2F;strong&gt; is the CHIP-8 virtual machine itself, memory, registers, the fetch-decode-execute cycle, all 34 standard instructions. It has zero platform knowledge, no SDL, no window, no sound. This separation means the core is testable in isolation and you could swap SDL for a terminal renderer without touching any of it. &lt;strong&gt;PLATFORM&lt;&#x2F;strong&gt; is the SDL2 layer, opening a window, drawing pixels, reading keyboard events, playing a buzzer tone. &lt;strong&gt;CLI&lt;&#x2F;strong&gt; is just glue, argument parsing, ROM loading, and the main loop that ties the other two together at 60 FPS. CORE never imports PLATFORM, communication is one-directional.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;chip-8-quirks&quot;&gt;CHIP-8 quirks&lt;&#x2F;h2&gt;
&lt;p&gt;I used &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;ampcode.com&#x2F;&quot;&gt;Amp&lt;&#x2F;a&gt; to help me write the specs. It made the process faster but the thinking still had to happen, because CHIP-8 has a bunch of documented ambiguities where original hardware, the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;COSMAC_VIP&quot;&gt;COSMAC VIP&lt;&#x2F;a&gt;, and later interpreters all behave differently. The specs had to make explicit choices for each of these and I had to read through multiple references to decide which behavior to implement.&lt;&#x2F;p&gt;
&lt;p&gt;The shift instructions are a good example. The opcode encodes both an &lt;code&gt;x&lt;&#x2F;code&gt; and &lt;code&gt;y&lt;&#x2F;code&gt; register, but the question is whether you shift &lt;code&gt;Vx&lt;&#x2F;code&gt; directly or shift &lt;code&gt;Vy&lt;&#x2F;code&gt; and store the result in &lt;code&gt;Vx&lt;&#x2F;code&gt;. The original COSMAC VIP did the latter, most modern interpreters expect the former. The spec goes with &quot;shift Vx, ignore Vy&quot;.&lt;&#x2F;p&gt;
&lt;p&gt;Then there&#x27;s what I&#x27;d call the VF trap. VF is both a general-purpose register and the flag register. If you write VF before computing the result of an instruction and &lt;code&gt;x&lt;&#x2F;code&gt; or &lt;code&gt;y&lt;&#x2F;code&gt; happens to be &lt;code&gt;0xF&lt;&#x2F;code&gt;, you corrupt the input. You have to compute the result first, then write VF last. Apparently this is the most common CHIP-8 emulator bug.&lt;&#x2F;p&gt;
&lt;p&gt;I also added a &lt;code&gt;prev_framebuffer&lt;&#x2F;code&gt; field that isn&#x27;t part of the standard at all. CHIP-8&#x27;s XOR-based drawing means games erase a sprite and immediately redraw it one pixel over to animate. Without frame blending you see the erased frame as a flash. More on this one later.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-build&quot;&gt;The build&lt;&#x2F;h2&gt;
&lt;p&gt;After writing the specs I ran &lt;code&gt;ossature validate&lt;&#x2F;code&gt; to make sure the content matched the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;docs.ossature.dev&#x2F;specs&#x2F;smd.html&quot;&gt;SMD format&lt;&#x2F;a&gt; Ossature expects. This is purely structural, no LLM involved, just checking that dependencies resolve and the format is correct. Then I ran &lt;code&gt;ossature audit&lt;&#x2F;code&gt; which sent each spec to an LLM for semantic review looking for ambiguities and gaps. It found a few and I fixed them. After the per-spec audits, Ossature runs a cross-spec audit automatically to check consistency across spec boundaries. The number of fix attempts for both audit and build is configurable.&lt;&#x2F;p&gt;
&lt;p&gt;Ossature supports any model provider that &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;ai.pydantic.dev&#x2F;&quot;&gt;Pydantic AI&lt;&#x2F;a&gt; supports, and you can set a different model for different roles, maybe use a more powerful model for auditing and a cheaper one for code generation. For chomp8 I kept it simple and used one model for everything, &lt;code&gt;google&#x2F;gemini-3.1-pro-preview&lt;&#x2F;code&gt; via OpenRouter.&lt;&#x2F;p&gt;
&lt;p&gt;After audit, Ossature produced a build plan with 15 tasks in dependency order. The plan is a TOML file you can read and edit before building. Each task lists what spec sections feed into its prompt, what files from earlier tasks get injected as context, and what verification command runs after generation. The instruction execution task for example got the Cycle and Draw Sprite spec sections plus a chip8 reference document as context, and saw the types and state modules from earlier tasks. But it didn&#x27;t see anything from the PLATFORM spec. Less context, less room for the model to get confused.&lt;&#x2F;p&gt;
&lt;p&gt;The build ran task by task. Each task generates code, runs &lt;code&gt;cargo check&lt;&#x2F;code&gt; or &lt;code&gt;cargo test&lt;&#x2F;code&gt;, and if verification fails a fixer agent reads the errors and tries to repair things. All prompts and responses are saved to &lt;code&gt;.ossature&#x2F;tasks&#x2F;&lt;&#x2F;code&gt; for traceability. One thing I found useful was that the strict separation between specs maps well to how you&#x27;d actually want to structure the code. Because CORE can&#x27;t see PLATFORM, the generated code naturally ended up with clean module boundaries. The LLM couldn&#x27;t accidentally import SDL types in the VM core because those types simply weren&#x27;t in the prompt.&lt;&#x2F;p&gt;
&lt;p&gt;Error handling was more prescriptive than I&#x27;d normally write in a spec. The spec says things like &quot;if &lt;code&gt;i + n - 1 &amp;gt; 4095&lt;&#x2F;code&gt;, error before touching the framebuffer.&quot; That level of detail feels excessive when writing code by hand, but for LLM generation it turned out to be exactly the right amount. Without it the model would probably have generated something that half-writes to memory before discovering the bounds error. This is the kind of detail that you sort of have to know to put in the spec, but once it&#x27;s there the LLM handles it fine.&lt;&#x2F;p&gt;
&lt;p&gt;The &lt;code&gt;prev_framebuffer&lt;&#x2F;code&gt; I mentioned earlier is a good example of what happens when the spec isn&#x27;t precise enough. The first build had visible sprite flicker, moving objects would briefly disappear and reappear each frame. The frustrating part was that the spec already anticipated the problem. The CORE spec defined &lt;code&gt;prev_framebuffer&lt;&#x2F;code&gt; and described it as &quot;used for frame blending to eliminate XOR-draw flicker,&quot; and the CLI spec had a step to initialize it. But the generated code never actually used it. Neither spec described the concrete algorithm, how to blend, when to snapshot, what to pass to the renderer. The field just sat there unused. The fix was to go back to the specs, not the code. I updated the CORE spec to spell out that display output is computed as &lt;code&gt;framebuffer[i] OR prev_framebuffer[i]&lt;&#x2F;code&gt;, and updated the CLI spec&#x27;s render step to explicit steps instead of a vague &quot;call platform render with the current VM framebuffer.&quot; After rebuilding, the flicker was gone. A field with a descriptive comment is a hint to a human but it&#x27;s noise to a code generator. If a spec defines a data structure, every reader and writer of that structure needs explicit steps referencing it, or it ends up as dead code in the output.&lt;&#x2F;p&gt;
&lt;p&gt;Writing specs takes longer than I initially expected. The format itself is straightforward, but you have to think through every decision before any code exists. That&#x27;s work you&#x27;d normally do while coding, spread across many small decisions you make without really noticing. Pulling it all forward into the spec phase felt slower at first but the generated code came out more coherent because of it. The SMD format also pushes you to be concrete. &quot;Handle invalid input&quot; is the kind of thing I might write in a design doc and move on. But the format wants to know what the input is, what happens on error, what the error message says.&lt;&#x2F;p&gt;
&lt;p&gt;I&#x27;m not sure this approach makes sense for everything. For a small script or a quick prototype, writing three spec files and running an audit would be overkill. But for something like an emulator where correctness matters and there are dozens of subtle behavioral decisions to make, having them all written down in one place before any code is generated felt like a real advantage. The repo is at &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;beshrkayali&#x2F;chomp8&quot;&gt;github.com&#x2F;beshrkayali&#x2F;chomp8&lt;&#x2F;a&gt;, the specs are in the &lt;code&gt;specs&#x2F;&lt;&#x2F;code&gt; directory if you want to see what the inputs looked like.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Playing IF Games with Natural Language</title>
        <published>2025-11-14T00:00:00+00:00</published>
        <updated>2025-11-14T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Beshr Kayali Reinholdsson
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://log.beshr.com/playing-if-with-natural-language/"/>
        <id>https://log.beshr.com/playing-if-with-natural-language/</id>
        
        <content type="html" xml:base="https://log.beshr.com/playing-if-with-natural-language/">&lt;p&gt;I&#x27;ve been experimenting with the idea of integrating LLMs with text-adventure and interactive fiction games in a couple of different ways, most are not yet ready (and will probably take a long time for anything useful to come out of them if any) but one area I wanted to share is introducing LLMs at the parser layer of the engine or the VM. From the minimal experience I have with the world of IF (other than just playing some games), the traditional parser is both the charm and possibly the barrier to IF games. You need to learn the syntax and figure out what verbs the game understands (some might be defaults&#x2F;common and some might be custom to the game), but mostly you have to phrase things in a very specific way. For example &quot;take key&quot; works but &quot;grab it&quot; does not, even though technically both mean the same thing.&lt;&#x2F;p&gt;
&lt;p&gt;But the game really just needs a normalized command like &quot;take key&quot; or &quot;go north&quot;, and doesn&#x27;t (or shouldn&#x27;t) care about how the player phrased it. So basically the interpretation of what the player meant is really just an I&#x2F;O problem, not a game logic problem. So this is where the idea came from: what if we use an LLM to handle that interpretation?&lt;&#x2F;p&gt;
&lt;p&gt;This experiment is built on top of &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.eblong.com&#x2F;zarf&#x2F;&quot;&gt;Andrew Plotkin&#x27;s&lt;&#x2F;a&gt; CheapGlk and Glulxe. I forked both and added a thin layer in the Glk library that intercepts user input and sends it to an OpenAI-compatible API for interpretation, then passes it back to the game as if the user wrote it. The API reads the last few lines of game output for context, tries to figure out what the player probably meant, and returns a &quot;normalized&quot; command (of course that might be more difficult than it seems because LLMs don&#x27;t &quot;think&quot;, but it does actually seem to work most of the time) and that&#x27;s it. The VM doesn&#x27;t change, the game files don&#x27;t change, nothing changes except the an additional step to parse out the intent of the player before it gets passed back to the game.&lt;&#x2F;p&gt;
&lt;p&gt;Here&#x27;s a demo playing &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;ifarchive.org&#x2F;indexes&#x2F;if-archive&#x2F;games&#x2F;glulx&#x2F;#Try_Again.gblorb&quot;&gt;Tom Devereaux&#x27;s &quot;Try Again&quot;&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
&lt;a href=&quot;demo.gif&quot; target=&quot;_blank&quot;&gt;
&lt;figure class=&quot;fullwidth&quot;&gt;
    &lt;img src=&quot;demo.gif&quot; alt=&quot;Gameplay example with modified Glk&#x2F;Glulxe to use LLM-based user input parsing&quot; &#x2F;&gt;
&lt;&#x2F;figure&gt;
&lt;&#x2F;a&gt;
&lt;p&gt;When you type something like &quot;let&#x27;s go through that metal door&quot;, the Glk library sends it to the LLM with context about the current scene (the bunker description, the objects you can see), gets back &quot;go through metal door&quot;, and passes that to the game.&lt;&#x2F;p&gt;
&lt;p&gt;The system reads room descriptions and object lists to understand context. When you say &quot;take it&quot; after opening a box with a pistol inside, it knows you mean &quot;take pistol&quot;. When you say &quot;read them&quot; in front of a filing cabinet with multiple entries, it starts with the first one. Say &quot;and the next one&quot; and it continues the sequence. This means existing games work without modification.&lt;&#x2F;p&gt;
&lt;p&gt;Almost nothing changed in Glulxe itself. I added OpenSSL to the build configuration and linked against the modified CheapGlk. The entire LLM integration lives in the Glk library, which seemed reasonable to me since Glk&#x27;s job is to handle input and output.&lt;&#x2F;p&gt;
&lt;p&gt;One interesting side effect is that because some LLMs are multilingual, you can play in different languages. The game still receives English commands but you could type in Swedish or transliterated Arabic and it would work the same way.&lt;&#x2F;p&gt;
&lt;p&gt;I wanted to answer a few questions with this: Can LLM interpretation make IF more accessible without destroying what makes it interesting? Does it preserve the puzzle-solving nature or does it just become &quot;tell the AI what you want and it figures it out&quot;? Can spatial reasoning be extracted from text descriptions well enough to understand what &quot;go through that metal door&quot; means in context? I think some answers will take more time to figure out but at least I can try playing some games now and see how it works.&lt;&#x2F;p&gt;
&lt;p&gt;There are some obvious issues though. Interpretation isn&#x27;t always perfect or consistent. LLM calls add latency and API costs can become high if you&#x27;re playing for hours. You&#x27;re dependent on external service availability unless you run a local model. Model quality varies a lot too. I&#x27;ve had good results with &lt;code&gt;google&#x2F;gemini-2.5-flash&lt;&#x2F;code&gt; but smaller models need significant finetuning to be useful (though I think this is probably where this idea should go next, a specialized finetuned SLM for parsing user input specifically for text-adventure games).&lt;&#x2F;p&gt;
&lt;p&gt;Although this is just a proof of concept, I tried to handle some edge cases. Some games ask for raw string input like your character&#x27;s name, you can wrap your input in brackets to skip LLM processing. When you try to take something that&#x27;s fixed in place, it passes that through and lets the game respond naturally.&lt;&#x2F;p&gt;
&lt;p&gt;The experiment is done entierly by adjusting Andrew Plotkin&#x27;s CheapGlk to call the external LLM provider. After building both CheapGlk and Glulxe, you add a configuration file at &lt;code&gt;~&#x2F;.glk_llm.conf&lt;&#x2F;code&gt; with the API endpoint you want to use, key, model, and a few other settings. You can use OpenAI, OpenRouter, local Ollama, or whatever supports the OpenAI chat completions format.&lt;&#x2F;p&gt;
&lt;p&gt;Is it actually fun? I have to play some more to be able to answer that, but it probably depends on what you want from IF. If you enjoy the puzzle of figuring out the parser itself, this removes that layer entirely. If you find the parser frustrating and just want to explore the story, with my limited test run with some games I found this to help a lot. The interpretation adds a different kind of uncertainty though. Sometimes the LLM makes unexpected choices about what you meant, which can be amusing or annoying depending on the situation.&lt;&#x2F;p&gt;
&lt;p&gt;I&#x27;m treating this as a prototype to explore these questions, not as a real feature or contribution. The code is minimal and possibly rough in places and there are definitely improvements to be made. But it&#x27;s functional enough to play through games and see how it feels.&lt;&#x2F;p&gt;
&lt;p&gt;If you want to try it yourself, check out the repos: &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;beshrkayali&#x2F;glulxe&quot;&gt;Glulxe fork&lt;&#x2F;a&gt; and &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;beshrkayali&#x2F;cheapglk&quot;&gt;CheapGlk fork&lt;&#x2F;a&gt;. Build instructions and configuration details are in the READMEs.&lt;&#x2F;p&gt;
&lt;p&gt;Update (2025-11-17)&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Added a WebAssembly (WASM) build to make testing easier. Instructions are in the READM, but I put up a hosted version: &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;beshr.com&#x2F;webglulxe&#x2F;&quot;&gt;https:&#x2F;&#x2F;beshr.com&#x2F;webglulxe&#x2F;&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;LLM API calls happen client-side in the browser via JavaScript.&lt;&#x2F;li&gt;
&lt;li&gt;To run your own version, build both CheapGlk and Glulxe to WASM as described in the README.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Freedom in Open Source</title>
        <published>2025-10-03T00:00:00+00:00</published>
        <updated>2025-10-03T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Beshr Kayali Reinholdsson
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://log.beshr.com/open-source/"/>
        <id>https://log.beshr.com/open-source/</id>
        
        <content type="html" xml:base="https://log.beshr.com/open-source/">&lt;p&gt;I&#x27;ve watched the open source world from a bit of a distance over the last 20 years  while learning to code and getting paid doing it (the first project I put out there, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;sourceforge.net&#x2F;projects&#x2F;backupod&#x2F;&quot;&gt;BackuPod&lt;&#x2F;a&gt;, was uploaded to SourceForge in 2007, I was a novice Python programmer.)&lt;&#x2F;p&gt;
&lt;p&gt;To me it seemed like the conversation at the time was dominated by people like Richard Stallman and his ideas about software freedom. It was all about the developer&#x27;s freedom to see the code, change it, and share it. It was a powerful statement against proprietary software, supportive of &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.catb.org&#x2F;~esr&#x2F;writings&#x2F;cathedral-bazaar&#x2F;hacker-history&#x2F;&quot;&gt;hackerdom&lt;&#x2F;a&gt; and the natural urge to tinker with things. Then you had Eric S. Raymond talking about the &quot;bazaar&quot; model, where all these individual developers working on their own things would somehow create something amazing. I didn&#x27;t really understand all this exactly back then, but what drew me to the idea was this focus on the creator&#x27;s liberty and ability (or even expectation) on the user to know what they&#x27;re using well enough and to be able to adjust it if they want, even if in a minimal way. The freedom was for the developer to build what they wanted, not necessarily to serve a massive userbase, but also for the userbase to feel like they&#x27;re not stuck using whatever the developer wanted them to use or do on their machines.&lt;&#x2F;p&gt;
&lt;p&gt;But as I progressed and learned more, open source appeared like an exclusive club with its own language and rules, and I never really broke in. I&#x27;ve contributed a patch here and there, felt happy about getting praised publically, used countless libraries of course, and dontated money to support those I used most, but I never became a &quot;maintainer&quot; or a core part of any project, and non of my open source projects drew a lot of attention. And honestly, looking at the state of things today, I&#x27;m pretty happy that things turned out this way.&lt;&#x2F;p&gt;
&lt;p&gt;The whole dynamic between the freedom of the creator and the duty to the user has become a real mess. This individualistic spirit is still there in a lot of projects but it&#x27;s getting crushed under the weight of modern expectations.&lt;&#x2F;p&gt;
&lt;p&gt;It might seem strange but I think what happened (and sort of the origin of the problem) is that open source won. It&#x27;s not a niche hobby anymore. It&#x27;s a fundamental infrastructure piece of the entire global tech economy. The Linux kernel, Apache, Python, and a random JavaScript library you&#x27;ve never heard of power a million websites. Corporations, governments, everyone depends on this stuff. And that dependency has created a strange shift in perception. Users start to see these projects not as a gift from a stranger but as a product. They treat it like commercial software and expect commercial-level support, reliability, and a roadmap that suits their needs. This created a perceived obligation to serve, which was never part of the original deal as I see it.&lt;&#x2F;p&gt;
&lt;p&gt;The first thing this directly led to is the maintainer&#x27;s burden. Most of these projects are run by one person (or a tiny team) in their spare time. They&#x27;re not getting paid, or if they are it&#x27;s not much. They carry the costs, the time spent debugging, the mental energy of planning new features, and the emotional toll of dealing with the public (good or bad comments). I&#x27;ve seen issue trackers that would make your skin crawl. The constant stream of demands, the entitlement, the pressure to add some feature that only one company needs. I personally can&#x27;t imagine dealing with large projects like this without burning out. And when a maintainer finally puts their foot down and says &quot;no&quot;, they get backlash. They&#x27;re called rude, or a gatekeeper for simply exercising the very autonomy that open source was supposed to be about. I think those who do maintain large projects and still seem sane have somehow managed to luck out into walking the fine line, but who knows maybe there are a few with a secret process that worked for them.&lt;&#x2F;p&gt;
&lt;p&gt;Part of the problem is this myth of the &quot;community&quot;. We talk about the open source community as if it&#x27;s some kind of democracy where everyone gets a vote, some utopia where people are somehow friends just because they both use Rust or Python. Back when I was doing a lot of Python on daily basis, I never felt part of the community and it always rubbed me the wrong way when I see people talk about it online. Most projects are a benevolent dictatorship or an oligarchy. One person or a small group makes the final call. But the collaborative rhetoric, all the talk about &quot;getting involved&quot; and &quot;contributions welcome&quot;, gives users a sense of entitlement I think. They feel if they open an issue they deserve a dialogue, that their feature request should be seriously debated. They don&#x27;t see the hundred other users making competing demands, or the fact that the maintainer&#x27;s vision for the project might just be different from theirs, or that they could just be wrong (this topic might deserve a post on its own). And now of course with AI and LLM-generated code, there&#x27;s an increasing number of patches and security-reports that are all fake or entirely LLM generated, wasting maintainers time, and there&#x27;s also a decent amount of new &quot;projects&quot; that are: open source, from afar seem like they&#x27;re something decent and useful, have nice READMEs and CI badges, 100% test coverage, etc... but are actually just junk and half-assed ideas someone auto generated to flex some muscle. The world of open source development and programming also suffered the popularity of attention economy, people treating themselves as brands and trying to get their name out their any way they can to carve themselves a slice of attention people give to things online, with zero fucks given about the quality of what they&#x27;re doing.&lt;&#x2F;p&gt;
&lt;p&gt;Of course there&#x27;s a whole spectrum of governance models trying to deal with this. You have the classic benevolent dictator for life like Linus Torvalds with the kernel, and then you have more consensus-driven projects like Debian. Some new ones will probably be needed for the LLM era (if it lasts). But for the vast majority of small or medium sized projects there is no formal governance. The decisions will be made on the fly, which will just lead to more conflict. Some projects try to manage this with strict contributor guidelines, but the attempt to reach a balance feels like we&#x27;ve already given up on the original meaning of open-source imho.&lt;&#x2F;p&gt;
&lt;p&gt;Not to be too negative, but I don&#x27;t think there&#x27;s a fix here really. The way things are going, I think we&#x27;ll inevitably see a more fragile software supply chain, where progress is dictated by corporate funding and not individual creativity, which is sad because it&#x27;ll push the ecosystem back towards a more centralized, commercially-controlled model that the free software movement originally fought against, but who knows.&lt;&#x2F;p&gt;
&lt;!-- Open source software embodies the ideal of shared creation, rooted in the freedom of individuals to build and share code as they see fit. Yet, as these projects become critical infrastructure for millions, a paradox emerges: maintainers, often volunteers, are free to define their vision, but users, developers, and corporations expect influence, collaboration, or even servitude to their needs. This tension fuels conflicts over decision-making, governance, and responsibility, threatening the sustainability of open source ecosystems. --&gt;
&lt;!-- This article examines the philosophical foundations of open source, how they clash with modern expectations of collective ownership, and what strategies can reconcile individual autonomy with the demands of a global userbase to ensure the long-term vitality of open source projects. --&gt;
&lt;!-- - The Philosophical Roots of Open Source Freedom --&gt;
&lt;!--   - Explore the origins of open source in the free software movement, emphasizing Richard Stallman’s principles of software freedom and Eric S. Raymond’s pragmatic “bazaar” model. --&gt;
&lt;!--   - Discuss how “freedom to create” was historically about empowering developers to build without proprietary constraints, not necessarily about serving a userbase. --&gt;
&lt;!--   - Examine how this individualistic ethos persists in maintainer-driven projects but is challenged by the scale of modern open source adoption. --&gt;
&lt;!-- - The Evolution of Open Source as Critical Infrastructure --&gt;
&lt;!--   - Highlight how open source has shifted from niche, hobbyist projects to foundational components of global technology (e.g., Linux, Apache, Python). --&gt;
&lt;!--   - Discuss the growing dependency of corporations, governments, and individuals on open source, which amplifies user expectations for responsiveness, reliability, and feature development. --&gt;
&lt;!--   - Explore how this shift creates a perceived “duty to serve,” as users treat open source like commercial software with implied support contracts. --&gt;
&lt;!-- - The Maintainer’s Burden: Autonomy vs. Obligation --&gt;
&lt;!--   - Analyze the volunteer nature of most open source maintenance, where individuals or small teams bear the emotional, intellectual, and time costs of managing projects. --&gt;
&lt;!--   - Discuss maintainer burnout caused by repetitive user requests, entitlement, or pressure to align with external priorities (e.g., corporate needs, community trends). --&gt;
&lt;!--   - Explore cases where maintainers assert autonomy by rejecting user demands, and the backlash this can provoke (e.g., accusations of rudeness or gatekeeping). --&gt;
&lt;!-- - User Expectations and the Myth of the “Community” --&gt;
&lt;!--   - Examine the misconception of open source projects as democratic “communities,” when many are driven by a single maintainer or small group with final authority. --&gt;
&lt;!--   - Discuss how users’ sense of entitlement stems from open source’s accessibility and collaborative rhetoric, leading to demands for dialogue or feature inclusion. --&gt;
&lt;!--   - Highlight the diversity of user stakeholders (casual users, contributors, corporations) and how their competing needs complicate maintainer decisions. --&gt;
&lt;!-- - Governance and Decision-Making in Open Source --&gt;
&lt;!--   - Explore the spectrum of governance models, from “benevolent dictator” (e.g., Linux kernel) to consensus-driven (e.g., Debian), and how they handle autonomy vs. collaboration. --&gt;
&lt;!--   - Discuss the lack of formal governance in many small-to-medium projects, leading to ad-hoc decision-making and potential conflicts. --&gt;
&lt;!--   - Analyze tools or frameworks (e.g., RFC processes, contributor guidelines) that balance maintainer control with user input. --&gt;
&lt;!-- - The Sustainability Crisis in Open Source --&gt;
&lt;!--   - Highlight the resource constraints of open source, including time, funding, and emotional energy, and how they exacerbate tensions between maintainers and users. --&gt;
&lt;!--   - Discuss the rise of funding models (e.g., GitHub Sponsors, Open Collective) and their impact on expectations—do financial contributions create a sense of “paying for service”? --&gt;
&lt;!--   - Examine the role of forking as a solution to disagreements, and why it’s often impractical due to community fragmentation or technical barriers. --&gt;
&lt;!-- - Cultural and Communication Challenges --&gt;
&lt;!--   - Explore how cultural differences in communication styles (e.g., direct vs. diplomatic) can escalate maintainer-user conflicts, especially in global, asynchronous communities. --&gt;
&lt;!--   - Discuss the role of platforms like GitHub or Codeberg in shaping interactions, where issue trackers can amplify repetitive demands or hostile exchanges. --&gt;
&lt;!--   - Highlight the emotional toll on maintainers when faced with criticism or entitlement, and the need for better norms around respectful engagement. --&gt;
&lt;!-- - Reconciling the Paradox: Strategies for Balance --&gt;
&lt;!--   - Propose solutions like transparent decision-making processes (e.g., documented rationales for rejecting features) to align expectations without compromising autonomy. --&gt;
&lt;!--   - Discuss the potential of community-driven governance models or rotating maintainer roles to distribute responsibility and reduce burnout. --&gt;
&lt;!--   - Explore training or resources for maintainers to manage user interactions effectively, fostering empathy without sacrificing control. --&gt;
&lt;!-- ----- --&gt;
&lt;!-- On a HN post ([macOS dotfiles should not go in –&#x2F;Library&#x2F;Application Support](https:&#x2F;&#x2F;news.ycombinator.com&#x2F;item?id=45022383) but the topic is not very important), user `orlp` wrote: --&gt;
&lt;!-- &gt; I and others have brought this up with the dirs Rust crate maintainer but they refuse to see it this way: [https:&#x2F;&#x2F;codeberg.org&#x2F;dirs&#x2F;dirs-rs&#x2F;issues&#x2F;64](https:&#x2F;&#x2F;codeberg.org&#x2F;dirs&#x2F;dirs-rs&#x2F;issues&#x2F;64). It&#x27;s very frustrating. --&gt;
&lt;!-- to which there was a reply from `bowsamic`: --&gt;
&lt;!-- &gt; Why is that soc guy so angry and rude about it? --&gt;
&lt;!-- then `orlp` replied: --&gt;
&lt;!-- &gt; I assume they&#x27;ve made up their mind and are now just tired of discussing it. I don&#x27;t know why they refuse to even consider an option for it. --&gt;
&lt;!-- The relevant bits of the comment from `soc` (from the linked issue) are: --&gt;
&lt;!-- &gt; As mentioned in other issue tickets: No. I&#x27;m not going to do this. You not wanting to follow OS rules doesn&#x27;t mean the rules are incorrect. If you want to do your own thing, write your own code or pick some other library. --&gt;
&lt;!-- and:  --&gt;
&lt;!-- &gt; I&#x27;m not going to have this discussion with you, see [dirs&#x2F;directories-rs#47 (comment)](https:&#x2F;&#x2F;codeberg.org&#x2F;dirs&#x2F;directories-rs&#x2F;issues&#x2F;47#issuecomment-2842511). --&gt;
&lt;!-- I have conflicting feelings about this little slice of open source work, on one hand I can imagine a potential scenario where this issue comes up many times and `soc` is tired of discussing it. This is not the kind of technical issue where there is a correct answer, it&#x27;s just opinions, and he happens to have one, if users don&#x27;t like it, why is there some expectation on him to comply, or even entertain the discussion? It&#x27;s his library and he can do whatever he wants with it. Those who disagree can fork it, start a new library, and do it their way, and if it turns out more people agree with the fork, the original&#x27;s popularity will decrease over time. --&gt;
&lt;!-- But on the other hand, I can also see the issue from `bowsamic` and `orlp` perspective. No body asked `soc` to create this library, and the usual reason for people to create an open source library is to provide some value to the userbase (or as people call it, &quot;community&quot; though I don&#x27;t like that word in this context very much). So it&#x27;s a bit strange why `soc` is refusing to have the discussion. If you&#x27;re doing something to please other users, why is having a discussion about a point of disagreement so impossible? Just because you had the discussion a thousand times before doesn&#x27;t make it reasonable to get discombobulated when a new person brings it up again (without knowning that this issue has been talked to death and there&#x27;ll never be consensus between library owner and library users). --&gt;
&lt;!-- It feels to me that there&#x27;s a sense of entitelement on both parts.  --&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>GroupTab</title>
        <published>2025-09-24T00:00:00+00:00</published>
        <updated>2025-09-24T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Beshr Kayali Reinholdsson
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://log.beshr.com/grouptab/"/>
        <id>https://log.beshr.com/grouptab/</id>
        
        <content type="html" xml:base="https://log.beshr.com/grouptab/">&lt;p&gt;The macOS app switcher (Cmd+Tab) is one of those things that&#x27;s just there and works well enough most of the time. But once you’re juggling a dozen apps, cycling a single list gets slow, and it becomes tedious to keep flipping back and forth between apps just to keep their order as you&#x27;d like it to be. The idea of having groups of apps (as rows) in the switcher felt natural to me once I implemented a quick PoC while working on &lt;a href=&quot;&#x2F;sudecku&quot;&gt;Sudecku&lt;&#x2F;a&gt; a few months ago.&lt;&#x2F;p&gt;
&lt;p&gt;Now I&#x27;m happy to share that I&#x27;ve developed that PoC into a proper app, GroupTab is a minimal grouped app switcher for macOS, so you can organize apps into visual rows and jump between groups quickly. I think it’s great for anyone who keeps many apps running simultaneously.&lt;&#x2F;p&gt;
&lt;p&gt;The app is $1.99, but I&#x27;m making it free until September 26 so you can try it and see if it actually improves your workflow.&lt;&#x2F;p&gt;
&lt;p&gt;Get it on the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;apps.apple.com&#x2F;us&#x2F;app&#x2F;grouptab&#x2F;id6751125313&quot;&gt;Mac App Store&lt;&#x2F;a&gt;. More screenshots and details &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;beshr.com&#x2F;grouptab&#x2F;&quot;&gt;on the website&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Would love to hear any feedback if you get a chance to try it.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Announcing Sudecku</title>
        <published>2025-08-26T00:00:00+00:00</published>
        <updated>2025-08-26T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Beshr Kayali Reinholdsson
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://log.beshr.com/sudecku/"/>
        <id>https://log.beshr.com/sudecku/</id>
        
        <content type="html" xml:base="https://log.beshr.com/sudecku/">&lt;p&gt;I&#x27;m thrilled to finally share something I&#x27;ve been working on for months. Sudecku &lt;label for=&quot;mn-icon&quot; class=&quot;margin-toggle&quot;&gt;⊕&lt;&#x2F;label&gt;
&lt;input type=&quot;checkbox&quot; id=&quot;mn-icon&quot; class=&quot;margin-toggle&quot;&#x2F;&gt;
&lt;span class=&quot;marginnote&quot;&gt;&lt;img src=&quot;&#x2F;sudecku.png&quot; &#x2F;&gt;&lt;&#x2F;span&gt; is a game that combines the timeless logic of Sudoku with the strategic depth of deck-building.&lt;&#x2F;p&gt;
&lt;p&gt;My wife and I enjoy playing Sudoku together, but she recently discovered the world of advanced puzzle variants through the Cracking the Cryptic YouTube channel. Watching Simon and Mark tackle these incredible spin-offs with killer cages, thermometers, arrows, and countless other rule variations was genuinely exciting. Each variant added fascinating new layers of logical thinking to the standard 9×9 grid.&lt;&#x2F;p&gt;
&lt;p&gt;The idea of Sudecku came up randomly, but initally it was very basic. I thought it&#x27;d be interesting to play Sudoku with playing cards and have some way to cheat by using power cards that are sort of like Uno&#x27;s action cards. The rest was the result of constant tweaking and testing while developing the game.&lt;&#x2F;p&gt;
&lt;p&gt;My wife gets a lot of credit for game play testing and coming up with ideas for how to make the game play fun and challenging. The name &quot;Sudecku&quot; is her idea as well! Honestly, the name is a major reason why I kept working on it, because it felt like a shame to waste such a good name.&lt;&#x2F;p&gt;
&lt;p&gt;What makes me most proud isn&#x27;t just the mechanics, it&#x27;s how the game feels. Whether you&#x27;re a Sudoku veteran or someone who&#x27;s never touched a logic puzzle, every puzzle offers those satisfying &quot;aha!&quot; moments. The strategic layer adds depth without overwhelming the core puzzle-solving joy that makes Sudoku so addictive.&lt;&#x2F;p&gt;
&lt;p&gt;This is technically my first personal iOS app. Writing Sudecku, I got to learn some Swift and some SpriteKit. I wrote earlier &lt;a href=&quot;&#x2F;notes-on-swift-from-building-an-ios-game&quot;&gt;this month&lt;&#x2F;a&gt; about some of what I learned.&lt;&#x2F;p&gt;
&lt;p&gt;There&#x27;s something deeply satisfying about seeing months of Swift code come together into fluid gameplay, especially when you&#x27;re building something you genuinely want to play yourself.&lt;&#x2F;p&gt;
&lt;p&gt;You can check it out on the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;apps.apple.com&#x2F;app&#x2F;sudecku&#x2F;id6747517140&quot;&gt;App Store&lt;&#x2F;a&gt; or learn more on the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;sudecku.com&quot;&gt;game&#x27;s website&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;This has been a true passion project, I&#x27;d love to hear what you think! Feel free to reach out with any comments.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Notes on Swift From Building an iOS Game</title>
        <published>2025-08-03T00:00:00+00:00</published>
        <updated>2025-08-03T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Beshr Kayali Reinholdsson
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://log.beshr.com/notes-on-swift-from-building-an-ios-game/"/>
        <id>https://log.beshr.com/notes-on-swift-from-building-an-ios-game/</id>
        
        <content type="html" xml:base="https://log.beshr.com/notes-on-swift-from-building-an-ios-game/">&lt;p&gt;&lt;i&gt;Update: The game is &lt;a href=&quot;&#x2F;sudecku&quot;&gt;now available&lt;&#x2F;a&gt;!&lt;&#x2F;i&gt;&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;p&gt;For the past few months I&#x27;ve been working on an iOS game. It&#x27;s almost finished now but I still would like to polish some aspects a bit more and look into what&#x27;s happening with iOS 26 and the new Games app before I publish it, to ensure things works well for everyone. I don&#x27;t want to give too many details just yet, but I can say it&#x27;s a puzzle&#x2F;card game. I will post more details when the game is available (hopefully within the month), stay tuned!&lt;&#x2F;p&gt;
&lt;p&gt;I think Swift is a fantastic language. Every new aspect I explored felt well-thought-out by the language designers. I was also pleasantly surprised by some smaller features that, while probably inconsequential in the grand scheme, I found neat, like argument labels, which as far as I know, are unique to Swift. &lt;label for=&quot;mn-arg-labels&quot; class=&quot;margin-toggle&quot;&gt;⊕&lt;&#x2F;label&gt;
&lt;input type=&quot;checkbox&quot; id=&quot;mn-arg-labels&quot; class=&quot;margin-toggle&quot;&#x2F;&gt;
&lt;span class=&quot;marginnote&quot;&gt;The idea is that argument labels can enhance code readability because they allow descriptive external names that clarify the purpose of parameters when calling the function. This makes some function calls a bit easier to understand and more self-documenting. By separating external and internal names, I could use concise internal names within the function body while maintaining names that explain the context from where it&#x27;s called . It&#x27;s pretty neat!&lt;&#x2F;span&gt;&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code data-lang=&quot;swift&quot;&gt;func sendMessage(to recipient: String, content message: String) {
    print(&amp;quot;Sending &amp;#39;\(message)&amp;#39; to \(recipient).&amp;quot;)
}

sendMessage(to: &amp;quot;Alice&amp;quot;, content: &amp;quot;Hello, how are you?&amp;quot;)
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Below are some of the features and patterns that really stood out to me. I&#x27;m sure some of these exist in other languages or frameworks but I don&#x27;t think I&#x27;ve seen them done exactly this way.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;enums&quot;&gt;Enums&lt;&#x2F;h2&gt;
&lt;p&gt;I found myself using enums far more extensively than I&#x27;ve done before in other languages, especially with their advanced capabilities.&lt;&#x2F;p&gt;
&lt;p&gt;Using String raw values for enums was incredibly practical. It allowed for type-safe references to asset names without relying on error-prone magic strings. The compiler catches typos, making changes quick and easy.&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code data-lang=&quot;swift&quot;&gt;enum MusicTrack: String {
    case mainMenuMusic = &amp;quot;MainMenu.mp3&amp;quot;
    case gameplayMusic = &amp;quot;GameplayLoop.mp3&amp;quot;
}

let trackName = MusicTrack.mainMenuMusic.rawValue &#x2F;&#x2F; &amp;quot;MainMenu.mp3&amp;quot;
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;It was also very nice to be able to represent different data types within a single enum. For &lt;code&gt;CardType&lt;&#x2F;code&gt; for example, having cases like &lt;code&gt;.number(String)&lt;&#x2F;code&gt; and &lt;code&gt;.powerup(PowerupType)&lt;&#x2F;code&gt; meant that each card type could carry its specific data directly. This meant that I didn&#x27;t need complex class hierarchies or multiple optional properties. It&#x27;s much cleaner this way.&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code data-lang=&quot;swift&quot;&gt;enum PowerupType: String, Codable {
    case extraTime = &amp;quot;Extra Time&amp;quot;
    case scoreMultiplier = &amp;quot;Score Multiplier&amp;quot;
}

enum CardType: Codable, Equatable {
    case number(String)
    case powerup(PowerupType)
}

let myCard = CardType.number(&amp;quot;7&amp;quot;)
let powerCard = CardType.powerup(.scoreMultiplier)
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Swift&#x27;s switch statements, especially with enums that have associated values, enforce exhaustive handling. If I added a new &lt;code&gt;PowerupType&lt;&#x2F;code&gt;, the compiler would immediately flag all switch statements that needed updating. This compile-time guarantee was very useful for preventing runtime bugs easily and made it simple for me to work on various aspects of the game in small chunks.&lt;label for=&quot;mn-ex-pattern-match&quot; class=&quot;margin-toggle&quot;&gt;⊕&lt;&#x2F;label&gt;
&lt;input type=&quot;checkbox&quot; id=&quot;mn-ex-pattern-match&quot; class=&quot;margin-toggle&quot;&#x2F;&gt;
&lt;span class=&quot;marginnote&quot;&gt; When I introduced &lt;code&gt;PowerCard&lt;&#x2F;code&gt;s I didn&#x27;t come up with all the ideas I wanted to do at once, and I wouldn&#x27;t have wanted to write them then anyway. It was very nice that I could add a new power card type to the enum whenever I get a new idea then have Xcode point out all the places I needed to update.&lt;&#x2F;span&gt;&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code data-lang=&quot;swift&quot;&gt;func handleCard(_ card: CardType) {
    switch card {
    case .number(let value):
        print(&amp;quot;Number card with value: \(value)&amp;quot;)
    case .powerup(let type):
        print(&amp;quot;Powerup card of type: \(type.rawValue)&amp;quot;)
    }
}
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;properties&quot;&gt;Properties&lt;&#x2F;h2&gt;
&lt;p&gt;For properties like &lt;code&gt;MusicManager.volume&lt;&#x2F;code&gt; or &lt;code&gt;isMuted&lt;&#x2F;code&gt;, the &lt;code&gt;didSet&lt;&#x2F;code&gt; observer allowed me to automatically persist the new value to &lt;code&gt;UserDefaults&lt;&#x2F;code&gt; and trigger an update to the audio player. This pattern keeps the logic for reacting to a property change directly co-located with the property itself.&lt;&#x2F;p&gt;
&lt;p&gt;This pattern of using &lt;code&gt;didSet&lt;&#x2F;code&gt; observers also helped encapsulate the &quot;what happens when this changes&quot; logic, which reduced the need for explicit method calls every time a property is modified. This made the code more self-contained and easier to keep up to date as I progressed, for example, or changed how scoring works.&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code data-lang=&quot;swift&quot;&gt;class MusicManager {
    var volume: Float = 0.5 {
        didSet {
            UserDefaults.standard.set(volume, forKey: &amp;quot;musicVolume&amp;quot;)
            updatePlayerVolume()
        }
    }

    private func updatePlayerVolume() {
        &#x2F;&#x2F; Logic to set actual player volume
        print(&amp;quot;Volume set to \(volume)&amp;quot;)
    }
}

let manager = MusicManager()
manager.volume = 0.7 &#x2F;&#x2F; didSet is automatically called here
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;I used computed properties for things like &lt;code&gt;MusicManager.isPlaying&lt;&#x2F;code&gt; (derived from the underlying &lt;code&gt;AVAudioPlayer&lt;&#x2F;code&gt;&#x27;s state) and &lt;code&gt;currentTrackName&lt;&#x2F;code&gt; (derived from &lt;code&gt;currentTrack&lt;&#x2F;code&gt;) to prevent redundant storage and ensure consistency. The value is always fresh.&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code data-lang=&quot;swift&quot;&gt;class MusicManager {
    var musicPlayer: AVAudioPlayer? &#x2F;&#x2F; Assume this exists
    var currentTrack: MusicTrack?

    var isPlaying: Bool {
        return musicPlayer?.isPlaying ?? false
    }

    var currentTrackName: String? {
        return currentTrack?.rawValue
    }
}
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Using computed properties in classes to read from and write to &lt;code&gt;UserDefaults&lt;&#x2F;code&gt; was particularly effective. It made persistent data feel like a regular stored property, simplifying access and modification while handling the &lt;code&gt;UserDefaults&lt;&#x2F;code&gt; interaction internally.&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code data-lang=&quot;swift&quot;&gt;struct Stats {
    static var cardsPlayed: Int {
        get {
            return UserDefaults.standard.integer(forKey: &amp;quot;cardsPlayedCount&amp;quot;)
        }
        set {
            UserDefaults.standard.set(newValue, forKey: &amp;quot;cardsPlayedCount&amp;quot;)
        }
    }
}

&#x2F;&#x2F; Usage:
Stats.cardsPlayed += 1 &#x2F;&#x2F; Reads, increments, writes back
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;optional-chaining-and-nil-coalescing&quot;&gt;Optional Chaining (?) and Nil Coalescing (??)&lt;&#x2F;h2&gt;
&lt;p&gt;These are fundamental for safe handling of optional values and significantly improve code readability.&lt;&#x2F;p&gt;
&lt;p&gt;Optional chaining (?) allows for concise and safe access to properties or methods on optional values. If any part of the chain is nil, the entire expression evaluates to nil without crashing. This is far cleaner than nested if let statements for simple access.&lt;&#x2F;p&gt;
&lt;p&gt;Nil coalescing (??) is a clean way to provide a default value if an optional is nil.&lt;&#x2F;p&gt;
&lt;p&gt;Together, optional chaining and nil coalescing drastically reduce the boilerplate associated with nil checks. It&#x27;s much nicer to have code that&#x27;s direct and easier to follow, especially when coming back to a function after a few weeks.&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code data-lang=&quot;swift&quot;&gt;var playerNode: SKNode? &#x2F;&#x2F; Could be nil
var gameScene: SKScene? &#x2F;&#x2F; Could be nil

&#x2F;&#x2F; Optional chaining:
playerNode?.position.x = 100 &#x2F;&#x2F; Only sets if playerNode is not nil
gameScene?.presentScene(SKScene()) &#x2F;&#x2F; Only presents if gameScene is not nil

&#x2F;&#x2F; Nil coalescing, scoreText default to &amp;quot;0&amp;quot; if totalStatsData is nil
let scoreText = totalStatsData?.getFormattedScore() ?? &amp;quot;0&amp;quot;
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;weak-and-unowned-references&quot;&gt;weak and unowned References&lt;&#x2F;h2&gt;
&lt;p&gt;Understanding and correctly applying weak and unowned was critical for memory management, especially with closures and SpriteKit animation-related code blocks.&lt;&#x2F;p&gt;
&lt;p&gt;I faced some trouble with retain cycles, obviously. In SpriteKit for example, with nodes, timers, and completion handlers, it&#x27;s easy to create strong reference cycles that lead to memory leaks and crashes that are hard to track. &lt;label for=&quot;mn-retain-cycles&quot; class=&quot;margin-toggle&quot;&gt;⊕&lt;&#x2F;label&gt;
&lt;input type=&quot;checkbox&quot; id=&quot;mn-retain-cycles&quot; class=&quot;margin-toggle&quot;&#x2F;&gt;
&lt;span class=&quot;marginnote&quot;&gt;What&#x27;s more annoying is that these crashes did not happen in the simulator, but only on real and slightly older hardware and never with dev builds.&lt;&#x2F;span&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Using &lt;code&gt;[weak self]&lt;&#x2F;code&gt; in capture lists for  (like &lt;code&gt;Timer&lt;&#x2F;code&gt; callbacks or &lt;code&gt;SKAction&lt;&#x2F;code&gt; completion blocks) is good for safer access to various variables in closures (with a &lt;code&gt;guard let self = self else { return })&lt;&#x2F;code&gt; for example). If &lt;code&gt;self&lt;&#x2F;code&gt; is deallocated, the &lt;code&gt;weak&lt;&#x2F;code&gt; reference becomes &lt;code&gt;nil&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code data-lang=&quot;swift&quot;&gt;class GameScene: SKScene {
    var gameTimer: Timer?

    func setupTimer() {
        gameTimer = Timer.scheduledTimer(withTimeInterval: 1.0, repeats: true) { [weak self] timer in
            &#x2F;&#x2F; Safely unwrap self. If GameScene is deallocated, self will be nil.
            guard let self = self else {
                timer.invalidate() &#x2F;&#x2F; Stop the timer if scene is gone
                return
            }
            self.updateGameTime() &#x2F;&#x2F; Safely call method on self
        }
    }

    func updateGameTime() {
        &#x2F;&#x2F; game time update logic
        print(&amp;quot;Game time updated.&amp;quot;)
    }
}
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Building this game was a lot of fun, if you&#x27;re interested in checking it out, check back here in a month or two, currently waiting for the tax agency in Sweden to finish my paper work.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Using nix-darwin</title>
        <published>2025-05-02T00:00:00+00:00</published>
        <updated>2025-05-02T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Beshr Kayali Reinholdsson
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://log.beshr.com/nix-darwin/"/>
        <id>https://log.beshr.com/nix-darwin/</id>
        
        <content type="html" xml:base="https://log.beshr.com/nix-darwin/">&lt;p&gt;As I&#x27;ve &lt;a href=&quot;&#x2F;switching-to-macos-again&quot;&gt;recently switched to macOS&lt;&#x2F;a&gt;, I decided to configure my system using &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;nix-darwin&#x2F;nix-darwin&quot;&gt;nix-darwin&lt;&#x2F;a&gt;. I&#x27;ve played around with Nix and NixOS before, and I&#x27;m in no way an expert, but I like the idea of declaratively defining my system config. It makes it easier to revert things back to the way they were at a certain point, and to track what sort of changes I&#x27;ve made over the years, aside from quicker setup when I need to start from scratch again.&lt;&#x2F;p&gt;
&lt;p&gt;For my dotfiles (&lt;code&gt;zsh&lt;&#x2F;code&gt;, &lt;code&gt;wezterm&lt;&#x2F;code&gt;, &lt;code&gt;tmux&lt;&#x2F;code&gt;, etc...) I went with simply symlinking things (with nix-darwin&#x27;s &lt;code&gt;activationScripts&lt;&#x2F;code&gt;) rather than having it managed in a more Nix-y way. I&#x27;d like to keep the mental load of learning things that I don&#x27;t interact with every day to a minimum, because I&#x27;m bound to forget, and as much as I enjoy configuring my tools, my aim has always been to do as much as necessary to reach a point where I touch my config less and less (the last time I made a change to my emacs config was &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;beshrkayali&#x2F;emacs&#x2F;commit&#x2F;cfe01613c11b2db1452066e3bfd79785d12c43cd&quot;&gt;2022&lt;&#x2F;a&gt;, but I took the opportunity to overhaul it now as I&#x27;ve migrated all my config to a single repo).&lt;&#x2F;p&gt;
&lt;p&gt;My system config and other dotfiles are here: &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;beshrkayali&#x2F;system&quot;&gt;https:&#x2F;&#x2F;github.com&#x2F;beshrkayali&#x2F;system&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;using-nix-darwin&quot;&gt;Using Nix-Darwin&lt;&#x2F;h2&gt;
&lt;p&gt;It was surprisingly easy to set things up with nix-darwin.&lt;&#x2F;p&gt;
&lt;p&gt;Since I use Homebrew, and nix-darwin doesn&#x27;t manage installing it, I had to install that manually.&lt;&#x2F;p&gt;
&lt;p&gt;First, installing Nix itself, the README recommended using either Nix (via &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;DeterminateSystems&#x2F;nix-installer?tab=readme-ov-file#determinate-nix-installer&quot;&gt;Nix installer from Determinate Systems&lt;&#x2F;a&gt;) or Lix (which I&#x27;ve never heard of before). The README also recommended installing the vanilla upstream Nix (by answering no to installing Determinate Nix).&lt;&#x2F;p&gt;
&lt;p&gt;I created a &lt;code&gt;flake.nix&lt;&#x2F;code&gt; and split my config into a separate &lt;code&gt;fdarwin.nix&lt;&#x2F;code&gt; module, as I&#x27;ve seen many people do.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-config&quot;&gt;The Config&lt;&#x2F;h2&gt;
&lt;blockquote&gt;
&lt;p&gt;Configurations docs are available online on &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;nix-darwin.github.io&#x2F;nix-darwin&#x2F;manual&#x2F;index.html&quot;&gt;nix-darwin&#x27;s github pages&lt;&#x2F;a&gt;, or locally by running the &lt;code&gt;darwin-help&lt;&#x2F;code&gt; command.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;One of my favorite aspects of nix-darwin is the ability to declaratively set macOS system preferences:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code data-lang=&quot;nix&quot;&gt;# System defaults
system.defaults = {
  screencapture.location = &amp;quot;~&#x2F;Pictures&#x2F;screenshots&amp;quot;;
  SoftwareUpdate.AutomaticallyInstallMacOSUpdates = true;

  NSGlobalDomain = {
    AppleKeyboardUIMode = 3;
  };

  dock = {
    autohide = true;
    orientation = &amp;quot;left&amp;quot;;
    show-process-indicators = false;
    show-recents = false;
    static-only = true;
    tilesize = 32;
  };

  finder = {
    AppleShowAllExtensions = true;
    ShowPathbar = true;
    FXEnableExtensionChangeWarning = false;
    FXPreferredViewStyle = &amp;quot;clmv&amp;quot;;
    ShowStatusBar = true;
  };
};
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;I&#x27;ve also enabled the nifty Touch ID auth for sudo commands&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code data-lang=&quot;nix&quot;&gt;security.pam.services.sudo_local.touchIdAuth = true;
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Most of my tools are installed via Homebrew (with nix-darwin&#x27;s Homebrew integration), but I still install a few essential core packages via &lt;code&gt;environment.systemPackage&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code data-lang=&quot;nix&quot;&gt;environment.systemPackages = with pkgs; [
  wget
  curl
  git
  htop
  ripgrep
];
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;and for Homebrew (I&#x27;ll probably change what&#x27;s installed frequently, check on &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;beshrkayali&#x2F;system&#x2F;blob&#x2F;master&#x2F;nix-darwin&#x2F;darwin.nix&quot;&gt;github&lt;&#x2F;a&gt; for latest):&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code data-lang=&quot;nix&quot;&gt;homebrew = {
  enable = true;
  onActivation = {
    autoUpdate = true;
    cleanup = &amp;quot;zap&amp;quot;;
  };

  brews = [ &#x2F;* CLI tools *&#x2F; ];
  casks = [ &#x2F;* GUI applications *&#x2F; ];
  masApps = { &#x2F;* App Store applications *&#x2F; };
};
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The &lt;code&gt;cleanup = &quot;zap&quot;&lt;&#x2F;code&gt; setting is to remove any manually installed Homebrew packages not defined in my config, keeping things clean and predictable.&lt;&#x2F;p&gt;
&lt;p&gt;I&#x27;ve also configured automatic garbage collection cleanups to run weekly.&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code data-lang=&quot;nix&quot;&gt;nix.gc = {
  automatic = true;
  interval = {
    Hour = 3;
    Minute = 15;
    Weekday = 7;  # Sunday
  };
  options = &amp;quot;--delete-older-than 7d&amp;quot;;
};
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Rather than managing symlinks manually, I used nix-darwin&#x27;s &lt;code&gt;activationScripts&lt;&#x2F;code&gt;. Ironically, this might be the most complicated part of my config. But it&#x27;s straightforward. We first set up variables for the home directory and repository path, then define an array of symlinks as source-target pairs (covering configuration files for &lt;code&gt;nix-darwin&lt;&#x2F;code&gt; itself, &lt;code&gt;Emacs&lt;&#x2F;code&gt;, and other dotfiles). The &lt;code&gt;mkSymlinkCmd&lt;&#x2F;code&gt; function generates shell commands for each symlink to handle various edge cases, like removing existing symlinks and creating timestamped backups of existing files before replacing them. This function is then mapped across all symlinks and joins the results.&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code data-lang=&quot;nix&quot;&gt;  system.activationScripts.extraActivation.text = let
    homeDir = config.users.users.beshr.home;
    repoPath = &amp;quot;${homeDir}&#x2F;src&#x2F;system&amp;quot;;

    # Define symlinks as source -&amp;gt; target pairs
    symlinks = [
      # Format: [source target]
      # - Nix Darwin
      [&amp;quot;${repoPath}&#x2F;nix-darwin&amp;quot; &amp;quot;&#x2F;etc&#x2F;nix-darwin&amp;quot;]
      # - Emacs
      [&amp;quot;${repoPath}&#x2F;emacs&amp;quot; &amp;quot;${homeDir}&#x2F;.emacs.d&amp;quot;]
      # - Other dotfiles
      [&amp;quot;${repoPath}&#x2F;wezterm.lua&amp;quot; &amp;quot;${homeDir}&#x2F;.wezterm.lua&amp;quot;]
      [&amp;quot;${repoPath}&#x2F;zshrc.zsh&amp;quot; &amp;quot;${homeDir}&#x2F;.zshrc&amp;quot;]
      [&amp;quot;${repoPath}&#x2F;tmux.conf&amp;quot; &amp;quot;${homeDir}&#x2F;.tmux.conf&amp;quot;]
      [&amp;quot;${repoPath}&#x2F;gitconfig&amp;quot; &amp;quot;${homeDir}&#x2F;.gitconfig&amp;quot;]
    ];

    # Function to generate symlink commands
    mkSymlinkCmd = link: let
      source = builtins.elemAt link 0;
      target = builtins.elemAt link 1;
    in &amp;#39;&amp;#39;
      # For ${source} -&amp;gt; ${target}
      if [ -L &amp;quot;${target}&amp;quot; ]; then
        echo &amp;quot;Removing existing symlink at ${target}...&amp;quot;
        rm &amp;quot;${target}&amp;quot;
      elif [ -e &amp;quot;${target}&amp;quot; ]; then
        echo &amp;quot;Backing up existing file at ${target}...&amp;quot;
        mv &amp;quot;${target}&amp;quot; &amp;quot;${target}.backup-$(date +%Y%m%d-%H%M%S)&amp;quot;
      fi
      echo &amp;quot;Creating symlink: ${source} -&amp;gt; ${target}&amp;quot;
      mkdir -p &amp;quot;$(dirname &amp;quot;${target}&amp;quot;)&amp;quot;
      ln -sfn &amp;quot;${source}&amp;quot; &amp;quot;${target}&amp;quot;
    &amp;#39;&amp;#39;;

  in &amp;#39;&amp;#39;
    echo &amp;quot;Setting up symlinks...&amp;quot;
    ${builtins.concatStringsSep &amp;quot;\n&amp;quot; (map mkSymlinkCmd symlinks)}
    echo &amp;quot;Symlink setup complete!&amp;quot;
  &amp;#39;&amp;#39;;
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;I&#x27;m quite satisfied with this hybrid approach. I benefit from Nix&#x27;s declarative system-wide configuration and package management, while maintaining flexibility with my dotfiles that remain easily editable outside the Nix ecosystem.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Switching to macOS again</title>
        <published>2025-04-29T00:00:00+00:00</published>
        <updated>2025-04-29T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Beshr Kayali Reinholdsson
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://log.beshr.com/switching-to-macos-again/"/>
        <id>https://log.beshr.com/switching-to-macos-again/</id>
        
        <content type="html" xml:base="https://log.beshr.com/switching-to-macos-again/">&lt;p&gt;I&#x27;ve switched to Macbook Pro as my main personal computing device again. The last time I used a Mac OS fulltime for personal computing was around 2012, after which I transitioned to a Thinkpad X1 Carbon. I used Arch Linux with i3 initially, then later Sway, and I was quite satisfied with the setup I had developed over the years.&lt;&#x2F;p&gt;
&lt;p&gt;During this period, I&#x27;ve owned two different X1 Carbon generations (4th and 7th), and both were excellent at first. My primary frustration with these devices is how quickly they developed issues. On my first Thinkpad, an entire column of keys including 9, O, L, and . stopped functioning after a couple of years of daily use. I tried replacing the keys thinking that the problem was with the mechanism, but had no success.&lt;&#x2F;p&gt;
&lt;p&gt;Other than that, the trackpad on these laptops was extremely imprecise and finicky, but the trackpoint worked great (after the initial learning curve). Unfortunately, even the trackpoint began to deteriorate in quality after the first year. The little red piece of rubbery plastic started get loose and became less reliable. I think my usage was fairly standard, these laptops are designed for power users after all, but the build quality turned out to be significantly lacking in my experience.&lt;&#x2F;p&gt;
&lt;p&gt;I decided to purchase a newer model, which I used for several years. This time, issues began with the fan, which would randomly stop working. I had it serviced once (a technician came to my office and replaced the fan), but it began failing again just a couple of weeks later. Around the same time, the screen started to flicker and randomly go black, to the point where it became almost impossible to use it as a laptop. At that point, I&#x27;d grown frustrated with the entire Thinkpad lineup. I expected premium quality to match their premium price. I continued using this last Thinkpad in docked mode for a while, eventually resorting to Arch on WSL on my Windows PC (which performed surprisingly well). My experience probably doesn&#x27;t reflect the quality of the entire Thinkpad lineup, but I wasn&#x27;t going to keep trying, these devices aren&#x27;t cheap.&lt;&#x2F;p&gt;
&lt;p&gt;My experience with Apple&#x27;s laptop build quality has been exceptional in the past, and I&#x27;ve been using an M1 Pro for work since 2020 (though most of the time I was connected to a remote linux VM) and it still looks and functions perfectly. So I recently decided to purchase one of the new M4 models for my personal daily driver and settled on the M4 Pro with 24GB of RAM and 512GB of storage. This configuration seemed to offered a good balance between price and future-proofing for me.&lt;&#x2F;p&gt;
&lt;p&gt;I&#x27;m not the biggest fan of macOS and sort of wary of the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.macrumors.com&#x2F;2025&#x2F;03&#x2F;12&#x2F;major-macos-16-redesign-biggest-since-big-sur&#x2F;&quot;&gt;possible redesign&lt;&#x2F;a&gt;, but it still suites me better than Windows, and I can navigate my way around customizing things better.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Apple&#x27;s Vision</title>
        <published>2023-06-07T00:00:00+00:00</published>
        <updated>2023-06-07T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Beshr Kayali Reinholdsson
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://log.beshr.com/vision-pro/"/>
        <id>https://log.beshr.com/vision-pro/</id>
        
        <content type="html" xml:base="https://log.beshr.com/vision-pro/">&lt;p&gt;Yesterday at WWDC 2023 Keynote, Apple unveiled its first &quot;spatial computing&quot; device &quot;Vision Pro&quot;. I had never heard of this term before, but apparently it&#x27;s been defined (since 2003) by &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Spatial_computing&quot;&gt;Simon Greenwold&lt;&#x2F;a&gt; as &quot;human interaction with a machine in which the machine retains and manipulates referents to real objects and spaces&quot;.&lt;&#x2F;p&gt;
&lt;p&gt;There&#x27;s not a lot to say about the technical details yet. I think the most intriguing aspects for me are the catadioptric lenses and the R1 chip and how it processes the camera&#x2F;sensor feed in real-time. The foveated rendering, and how they&#x27;ve handled gaze and hand gesture tracking in the OS.&lt;&#x2F;p&gt;
&lt;p&gt;A few thoughts came to my mind while watching the announcement.&lt;&#x2F;p&gt;
&lt;p&gt;Firstly, it looks like a snorkeling mask! Jokes aside though, the technical aspects that make it all work together are very interesting for sure, and the device is seductive and obviously manufactured with high quality material and attention to detail.&lt;&#x2F;p&gt;
&lt;p&gt;At this point most people know that Apple does some of the most impressive marketing in the world. With that being said, the last couple of WWDC keynotes gave me a weird ominous creepy feeling with all the fake smiling and the excessive amount of happiness some people have for &quot;stickers in Messages&quot; and the formulaic talking points they use.&lt;&#x2F;p&gt;
&lt;p&gt;Secondly, I don&#x27;t think this is a productivity device as they&#x27;re selling it as, at least not in its current form. As someone commented on HN, the number of displays one has on their real desk and their size is usually not a major factor of productivity for most people, it&#x27;s their neck movement and the pain it entails.&lt;&#x2F;p&gt;
&lt;p&gt;If you have to twist your body around while sitting behind a desk (assuming you&#x27;re typing) you&#x27;re probably not going to want to move your neck a lot, so it&#x27;s probably just easier to do it without having any extra weight on your head (actually we don&#x27;t know the weight yet). I think this will be a consumption device first and foremost. To watch movies, play games, or do those weird meditation&#x2F;sleeping rituals.&lt;&#x2F;p&gt;
&lt;p&gt;I doubt that anyone who&#x27;s not a millionaire would be willing to fork $3500 for a toy, but people keep buying the latest iPhones while complaining they can&#x27;t afford to save for buying a house, so I&#x27;m not sure what will happen.&lt;&#x2F;p&gt;
&lt;p&gt;Thirdly, people are slowly but surely gaining more awareness about the unintentional effects of various tech gadgets on our lives. I can&#x27;t imagine why an average person who thinks of themselves as &quot;mindful&quot; of their tech usage would be interested in this.&lt;&#x2F;p&gt;
&lt;p&gt;Many design aspects of Vision Pro cater to the idea of being &quot;more present&quot; with others (from the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.apple.com&#x2F;v&#x2F;apple-vision-pro&#x2F;a&#x2F;images&#x2F;overview&#x2F;design&#x2F;portrait_front_base__gmqifatci56q_large_2x.jpg&quot;&gt;fake eyes&lt;&#x2F;a&gt; on the outward front display, to &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;developer.apple.com&#x2F;videos&#x2F;play&#x2F;wwdc2023&#x2F;10260&#x2F;&quot;&gt;Share Play in visionOS&lt;&#x2F;a&gt;, but if someone wants to maintain presence with others, why not just take it off when they&#x27;re talking to them? If your goal is to watch a movie with others, why not meet up IRL?&lt;&#x2F;p&gt;
&lt;p&gt;Maybe the &quot;cool factor&quot; is gripping. But surely not at this price? Even if they fix the battery and the price in the next couple of versions, I think it&#x27;ll be hard to convince people to act like it&#x27;s normal to sit and talk with someone wearing a diving mask in their living room, with 12 different cameras vaguely pointing in their direction, right? Most would feel weirded out with just one camera pointing in their direction.&lt;&#x2F;p&gt;
&lt;p&gt;There are many questions that will be answered in time, like what will happen if that magnetic battery cable gets unplugged unintentionally? Will the whole device turn off? Will they sell bigger batteries or a &quot;wall-plug&quot; option? How will the tracking work in various light conditions? Will Apple make a smaller AR-only option that&#x27;s actually more like glasses rather than some high-tech gas mask?&lt;&#x2F;p&gt;
&lt;p&gt;I don&#x27;t know how this will go, it&#x27;s interesting to witness it though. Many people are glued to their phone and it&#x27;s difficult to find anyone walking around without earbuds, it&#x27;s hard to imagine that there was a time when people didn&#x27;t do that, how did this transformation even happen? It feels like this could be a good opportunity to see how that transformation takes place in real-time.&lt;&#x2F;p&gt;
&lt;p&gt;If this vision of Apple fails, then it fails, as I would expect honestly, unless they manage to &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.forbes.com&#x2F;sites&#x2F;johnkoetsier&#x2F;2023&#x2F;06&#x2F;07&#x2F;apple-vision-pro-is-perfect-for-lucrative-military-contracts-apple-just-bought-a-company-that-can-help&#x2F;&quot;&gt;sell it to the military&lt;&#x2F;a&gt; somehow.&lt;&#x2F;p&gt;
&lt;p&gt;If it succeeds and becomes a lucrative market, we&#x27;ll probably see a Google version (sort of Daydream 2.0) and developers will rush to make apps and money. Meta will &quot;pivot&quot; and also make an AR thing. Will most people own one of these in 2035? Will it be normal to have 4 or 5 people sitting around a living room jacked up to Apple&#x27;s Vision just like how it&#x27;s (almost) normal now to do the same with phones. That sounds like a lonely and sad future, but at least we would&#x27;ve had an opportunity to witness how this transformation took place.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Writing Better</title>
        <published>2023-04-21T00:00:00+00:00</published>
        <updated>2023-04-21T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Beshr Kayali Reinholdsson
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://log.beshr.com/write-better/"/>
        <id>https://log.beshr.com/write-better/</id>
        
        <content type="html" xml:base="https://log.beshr.com/write-better/">&lt;p&gt;Over the past decade or so in my career, I have come to recognize the importance of writing well. This includes writing better emails, instant messages on IRC&#x2F;Slack&#x2F;Teams, documentation, and any other type of writing.&lt;&#x2F;p&gt;
&lt;p&gt;I believe that the key to writing effectively is to be able to communicate an idea in a straightforward and precise way. This is something I have noticed in my work as a programmer, but I believe it can be applied to any field. The point is not necessarily just for the benefit of others who are on the receiving end, but also for my own sake in actually saying what I intend to say and get others to understand it. I have seen many colleagues and friends communicate in a less-than-ideal way and I have felt both sympathetic and at-times vexed for their confused and hazy way of putting forward an idea. It&#x27;s mostly sad when they actually have a good idea but they just can&#x27;t bother (or just don&#x27;t have the ability) to think about it and write it clearly. I often find myself replying &quot;Do you mean ...?&quot; when someone asks me a question.&lt;&#x2F;p&gt;
&lt;p&gt;Using uncommon slang, lacking capitalization or punctuation can also affect the intelligibility of a request, this is especially the case for people whose first language is not English. I&#x27;m not a grammar pedant and English is not my first language. I&#x27;m not arguing that people should never miss a comma or a full stop, I certainly do that all the time, but there&#x27;s something to say for sure about how some of these rules at least can help in structuring ideas and thoughts.&lt;&#x2F;p&gt;
&lt;p&gt;I suppose what I&#x27;m arguing for here is not that we should all practice writing and respect grammar rules, but more that we should understand the value of clearly conveying thoughts in writing, especially in non-formal contexts in a work environment (like during chats or quick-meetings). It&#x27;s very easy to lose on potentially useful discussions that get missed (or dismissed) because they are slurred or down right incomprehensible.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Introduction Chapters</title>
        <published>2023-04-16T00:00:00+00:00</published>
        <updated>2023-04-16T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Beshr Kayali Reinholdsson
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://log.beshr.com/read-the-intro/"/>
        <id>https://log.beshr.com/read-the-intro/</id>
        
        <content type="html" xml:base="https://log.beshr.com/read-the-intro/">&lt;p&gt;I have recently identified a habit of mine whereby I tend to skip reading introductory chapters of books, at times only resorting to skimming through it in search of salient information. However, I have noticed that when I eventually take the time to read it word for word, it can offer valuable insights and contextual understanding of the material presented. It is, however, essential to exercise selectivity when reading to determine the relevant content, depending on the type of book. While reference books are intended to provide quick and easy access to pertinent information, narrative books such as biographies, histories, and essay collections are to be read cover-to-cover.&lt;&#x2F;p&gt;
&lt;p&gt;The issue with introductory chapters is that they are frequently weighed down by superfluous and trivial details that detract from the substance of the topic.&lt;&#x2F;p&gt;
&lt;p&gt;It is expected that introductory chapters should provide contextual information, set expectations, and clarify the author&#x27;s thesis and main ideas. The ideal introductory chapter for me would be characterized by brevity, clarity, and a critical analysis of the subject matter, as opposed to being overly promotional or generic in its approach. The ones that I am annoyed by the most are the ones that are over-the-top funny or witty.&lt;&#x2F;p&gt;
&lt;p&gt;While skipping (or skimming) introductory chapters may seem like a time-saving trick, it often results in missing out on valuable insights and context that can enhance understanding of the book. Therefore, it is essential for authors to be mindful of the purpose of an introduction chapter, and be more selective in determining the relevant content and tone.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>On note taking with Zettlekasten</title>
        <published>2023-03-15T00:00:00+00:00</published>
        <updated>2023-03-15T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Beshr Kayali Reinholdsson
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://log.beshr.com/taking-notes/"/>
        <id>https://log.beshr.com/taking-notes/</id>
        
        <content type="html" xml:base="https://log.beshr.com/taking-notes/">&lt;p&gt;I found out about the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;zettelkasten.de&#x2F;posts&#x2F;overview&#x2F;#the-introduction-to-the-zettelkasten-method&quot;&gt;Zettlekasten note taking method&lt;&#x2F;a&gt; in early 2021 and got interested in learning more about it. So I started using it with Emacs using using &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.orgroam.com&#x2F;&quot;&gt;Org-roam&lt;&#x2F;a&gt; and &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;jblevins.org&#x2F;projects&#x2F;deft&#x2F;&quot;&gt;Deft&lt;&#x2F;a&gt;, and a &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;beshrkayali&#x2F;emacs&#x2F;blob&#x2F;e1db2af762d0a0a0d3eb0dbc9241512cd80ca9c3&#x2F;custom&#x2F;setup-orgmode.el#L158-L177&quot;&gt;quick config&lt;&#x2F;a&gt; I threw together. I synced my notes to my Nextcloud instance.&lt;&#x2F;p&gt;
&lt;p&gt;After a few months of on-and-off usage, I found that learning how to properly employ Zettlekasten in my daily scenarios required me to go out of my way to remember to take notes in a Zettlekasten-y way.&lt;&#x2F;p&gt;
&lt;p&gt;It took daily practice and regular usage for the method to become ingrained. Aside from the time it took to get comfortable with &lt;code&gt;org-roam&lt;&#x2F;code&gt; itself, I found that it can be a lot of dull work to employ the idea of fleeting note taking and regular sessions of connecting between the notes and rearranging them, keeping what&#x27;s needed and trashing the frivolous.&lt;&#x2F;p&gt;
&lt;p&gt;I do a lot of research on various topics that I&#x27;m interested in, but I haven&#x27;t managed to employ it as a note taking method consistently enough while working on larger projects. I like the fact that I can use something like &lt;code&gt;org-roam&lt;&#x2F;code&gt; within Emacs, but it can also be awkward at times as I usually have other things opened there and switching around between code buffers and lots of note buffers can get annoying.&lt;&#x2F;p&gt;
&lt;p&gt;Having simple markdown &lt;em&gt;permanent&lt;&#x2F;em&gt; note files that are: longer, more conceptual, and more free-form always seemed to be a better option for me. I could restructure the little paragraphs and sentences in a single project file faster and easier. I didn&#x27;t find actual use for the &quot;connected web of thoughts&quot; idea other than the cool visual it can provide.&lt;&#x2F;p&gt;
&lt;p&gt;Looking over the notes that I have written so far, I think I can discard about 90% of them. But I was also very happily surprised to find a few quotes I liked from a book I was reading, a couple of bookmakrs, and some bits of random articles I have read and decided to preserve for some reason.&lt;&#x2F;p&gt;
&lt;p&gt;Currently I think of it like a diary for my laptop. It helps me remember what I did previously and connect the dots of where I started and ended on a specific topic (with &lt;code&gt;roam-tags&lt;&#x2F;code&gt;). I&#x27;d like to write a simple program at some point to combine between the idea of being able to create, collect and connect smaller notes in a Zettlekasten-manner, and being able to quickly rearranged together into a longer note format format automatically. I&#x27;d also like to be able to start multiple instances of this program together, one for each project basically for better brain-space isolation.&lt;&#x2F;p&gt;
&lt;h5 id=&quot;useful-links&quot;&gt;Useful links&lt;&#x2F;h5&gt;
&lt;ul&gt;
&lt;li&gt;Org-roam: &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;orgroam.com&quot;&gt;https:&#x2F;&#x2F;orgroam.com&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;My emacs setup: &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;beshrkayali&#x2F;emacs&quot;&gt;https:&#x2F;&#x2F;github.com&#x2F;beshrkayali&#x2F;emacs&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;Deft: &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;jblevins.org&#x2F;projects&#x2F;deft&#x2F;&quot;&gt;https:&#x2F;&#x2F;jblevins.org&#x2F;projects&#x2F;deft&#x2F;&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;Setting up Org-roam with Deft: &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.orgroam.com&#x2F;manual.html#Full_002dtext-search-with-Deft&quot;&gt;https:&#x2F;&#x2F;www.orgroam.com&#x2F;manual.html#Full_002dtext-search-with-Deft&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>&quot;Glitch&quot; Journalism</title>
        <published>2022-11-13T00:00:00+00:00</published>
        <updated>2022-11-13T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Beshr Kayali Reinholdsson
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://log.beshr.com/glitch-journalism/"/>
        <id>https://log.beshr.com/glitch-journalism/</id>
        
        <content type="html" xml:base="https://log.beshr.com/glitch-journalism/">&lt;p&gt;Using the term &quot;glitch&quot; when it comes to issues related to software or technology in general is bad journalism.&lt;&#x2F;p&gt;
&lt;p&gt;The term is used by journalists, politicians (and unfortunately, technicians and specialists) as a way to gloss over the details of what exactly is the &lt;strong&gt;cause&lt;&#x2F;strong&gt; of an issue.&lt;&#x2F;p&gt;
&lt;p&gt;A simple example to make the point. Suppose you have to make an important phone call one morning at 08:00 exactly but you forgot to charge your phone the night before. When you woke up your phone was dead so you couldn&#x27;t make the call. It&#x27;s not the end of the world of course, but it&#x27;s also your responsibility to have remembered to charge your phone. Saying that you couldn&#x27;t call because of a glitch with your phone or charger is not an acceptable excuse.&lt;&#x2F;p&gt;
&lt;p&gt;In reality, the term is mainly used as a way to conceal human error and make it seem like the bug couldn&#x27;t be helped and it&#x27;s no one&#x27;s fault.&lt;&#x2F;p&gt;
&lt;p&gt;A quick example:&lt;&#x2F;p&gt;
&lt;style&gt;.embed-container { position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden; max-width: 100%; } .embed-container iframe, .embed-container object, .embed-container embed { position: absolute; top: 0; left: 0; width: 100%; height: 100%; }&lt;&#x2F;style&gt;&lt;div class=&#x27;embed-container&#x27;&gt;&lt;iframe src=&#x27;https:&#x2F;&#x2F;www.youtube-nocookie.com&#x2F;embed&#x2F;copj0fPPfFk&#x27; frameborder=&#x27;0&#x27; allowfullscreen&gt;&lt;&#x2F;iframe&gt;&lt;&#x2F;div&gt;
&lt;p&gt;At best, it&#x27;s the technical equivilant to &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.youtube-nocookie.com&#x2F;embed&#x2F;ioGEI_UO81Q&quot;&gt;the yada yada phrase made popular in Seinfeld&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;The problem is not only that using &quot;glitch&quot; is useless and gives us no actual details as to the &lt;em&gt;why&lt;&#x2F;em&gt;, but in many cases, it&#x27;s used intentionally to obscure or disguise the truth.&lt;&#x2F;p&gt;
&lt;p&gt;Even in instances where the term is used as a synonym for a software bug, it&#x27;s still used incorrectly. In software, the bug itself is the &lt;em&gt;result&lt;&#x2F;em&gt; of something and not the &lt;em&gt;cause&lt;&#x2F;em&gt;. The &lt;em&gt;cause&lt;&#x2F;em&gt; could be any number of reasons, if you&#x27;re writing C code for example and you forgot to finish a comment with a &lt;code&gt;*&#x2F;&lt;&#x2F;code&gt; (which inadvertently commented out a big chunk of code after that, which itself resulted in a bug) is the actual cause. If you&#x27;re writing software for airline ticketing and did the same error it&#x27;s not acceptable for the company to tell their customers that &quot;a glitch&quot; caused people&#x27;s flight tickets to be cancelled. It&#x27;s reasonable to expect that a reporter covering the issue will try to dig deeper to find out what exactly is the reason that happened, &quot;a glitch&quot; doesn&#x27;t tell me much. They don&#x27;t have to explain the bug in detail as indeed most readers from the public won&#x27;t understand the meaning if they&#x27;re not programmers, but maybe the fact that that kind of code made it to produciton for example (or it was allowed to run on production data) calls into question the entire software development lifecycle and process followed at that company. This is what I want to know.&lt;&#x2F;p&gt;
&lt;p&gt;Obviously, it&#x27;s in the interest of companies&#x27; PR (and politicians) to use &quot;glitch&quot; because it muddles up the issue in a way that &lt;em&gt;seems&lt;&#x2F;em&gt; like an answer that -at best- doesn&#x27;t mean anything, and at worst, it makes it seem like a fluke and just an qaccident that couldn&#x27;t have been prevented, so there&#x27;s nothing to compensate and no one to hold accountable. It&#x27;s the job of the media to understand what happened so we can get to the bottom of an issue. When non-tech journalists do this, it&#x27;s bad, but when technology journalists do it, it&#x27;s detrimental.&lt;&#x2F;p&gt;
&lt;p&gt;The level of responsibility and accountability for why something happened depends on the skills and qualifications of the person responsible for the supposed &quot;glitch&quot;. A junior engineer dropping a database table by mistake is not their fault at all (and hopefully a recoverable issue if there are backups) but calls into question the process of onboarding or documentation at the company. If the dropped table is a couple of articles from an ecommerce website, it&#x27;s probably not that big of a deal, but if it&#x27;s the only copy of tests results of a patient then it&#x27;s a big deal.&lt;&#x2F;p&gt;
&lt;p&gt;Journalists should not be satisfied with &quot;glitch&quot; and ought to call out businesses and politicians when they use it.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;small&gt;&lt;i&gt;h&#x2F;t to &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.noagendashow.net&#x2F;&quot;&gt;NoAgenda show&lt;&#x2F;a&gt;.&lt;&#x2F;i&gt;&lt;&#x2F;small&gt;&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Where exactly does Python 3.11 get its ~25% Speedup?</title>
        <published>2022-10-28T00:00:00+00:00</published>
        <updated>2022-10-28T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Beshr Kayali Reinholdsson
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://log.beshr.com/python-311-speedup-part-1/"/>
        <id>https://log.beshr.com/python-311-speedup-part-1/</id>
        
        <summary type="html">&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.python.org&#x2F;downloads&#x2F;release&#x2F;python-3110&#x2F;&quot;&gt;Python 3.11&lt;&#x2F;a&gt; was released a few days ago and as usual, it comes with more than a few new features that make it ever more interesting, from &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;peps.python.org&#x2F;pep-0654&#x2F;&quot;&gt;exception groups&lt;&#x2F;a&gt; and &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;peps.python.org&#x2F;pep-0657&#x2F;&quot;&gt;fine-grained error locations and tracebacks&lt;&#x2F;a&gt; to &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;peps.python.org&#x2F;pep-0680&#x2F;&quot;&gt;TOML parsing support in the standard library&lt;&#x2F;a&gt; and of course the much awaited speedup as part of the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;faster-cpython&quot;&gt;faster CPython project&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;</summary>
        
    </entry>
    <entry xml:lang="en">
        <title>Oud tuning and string replacement</title>
        <published>2021-07-10T00:00:00+00:00</published>
        <updated>2021-07-12T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Beshr Kayali Reinholdsson
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://log.beshr.com/oud-tuning-and-strings/"/>
        <id>https://log.beshr.com/oud-tuning-and-strings/</id>
        
        <summary type="html">&lt;p&gt;I found out that the order in which Oud strings are connected to their pegs when replacing the strings is important for a few reasons.
It makes the neck look pretty, but more importantly, it makes the tuning more accurate when replacing strings, because it becomes easier to make sure that strings are not touching each other.&lt;&#x2F;p&gt;</summary>
        
    </entry>
    <entry xml:lang="en">
        <title>A Tour of DK EyeWitness CD encyclopedias from the 90s</title>
        <published>2021-06-26T00:00:00+00:00</published>
        <updated>2021-06-26T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Beshr Kayali Reinholdsson
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://log.beshr.com/dk-eyewitness-tour/"/>
        <id>https://log.beshr.com/dk-eyewitness-tour/</id>
        
        <summary type="html">&lt;p&gt;For the last couple of days, I&#x27;ve been going through all sorts of nostalgia going over DK EyeWitness CD encyclopedias from the 90s. Although I understood about 15% at best at that time, I distinctly remember spending hours clicking around, watching images, animations, videos, and listening to the fantastic narration in the encyclopedias of Science, and of Space and the Universe.&lt;&#x2F;p&gt;</summary>
        
    </entry>
    <entry xml:lang="en">
        <title>Degrees of nonlinearity</title>
        <published>2021-05-20T00:00:00+00:00</published>
        <updated>2021-05-20T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Beshr Kayali Reinholdsson
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://log.beshr.com/degrees-of-non-linearity/"/>
        <id>https://log.beshr.com/degrees-of-non-linearity/</id>
        
        <summary type="html">&lt;p&gt;The following is a summarized excerpt from the &lt;em&gt;Interactive Plots &amp;amp; Non-linearity&lt;&#x2F;em&gt; section of &quot;Scriptwriting for Games&quot; from the International Game Developers Association.&lt;&#x2F;p&gt;</summary>
        
    </entry>
    <entry xml:lang="en">
        <title>Inspect network traffic of an iOS app</title>
        <published>2021-04-03T00:00:00+00:00</published>
        <updated>2021-04-03T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Beshr Kayali Reinholdsson
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://log.beshr.com/inspect-network-traffic-on-ios/"/>
        <id>https://log.beshr.com/inspect-network-traffic-on-ios/</id>
        
        <summary type="html">&lt;p&gt;I needed access to some of the endpoints used by an iOS app, which also happened to be terrible. There are a couple of different ways to achieve this, probably the simplest of which is to run a proxy somewhere, and route traffic through it. Today I found out about &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;mitmproxy.org&#x2F;&quot;&gt;mitmproxy&lt;&#x2F;a&gt; which makes inspecting web traffic going through it very simple.&lt;&#x2F;p&gt;</summary>
        
    </entry>
    <entry xml:lang="en">
        <title>Debugging macros in Nim</title>
        <published>2021-04-02T00:00:00+00:00</published>
        <updated>2021-04-02T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Beshr Kayali Reinholdsson
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://log.beshr.com/debugging-macros-in-nim/"/>
        <id>https://log.beshr.com/debugging-macros-in-nim/</id>
        
        <summary type="html">&lt;p&gt;Nim provides three essential macros in the built-in &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;nim-lang.org&#x2F;docs&#x2F;macros.html&quot;&gt;macros&lt;&#x2F;a&gt;
module that are very helpful when writing or debugging macros. They are: &lt;code&gt;dumpTree&lt;&#x2F;code&gt;, &lt;code&gt;dumpAstGen&lt;&#x2F;code&gt; and &lt;code&gt;expandMacros&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;</summary>
        
    </entry>
    <entry xml:lang="en">
        <title>Capture stack trace when queries are executed</title>
        <published>2021-03-30T00:00:00+00:00</published>
        <updated>2021-03-30T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Beshr Kayali Reinholdsson
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://log.beshr.com/capture-stack-trace-when-queries-are-executed/"/>
        <id>https://log.beshr.com/capture-stack-trace-when-queries-are-executed/</id>
        
        <summary type="html">&lt;p&gt;Asserting query counts in Django tests with &lt;code&gt;CaptureQueriesContext&lt;&#x2F;code&gt; is a great way to maintain&#x2F;optimize code, but it doesn&#x27;t provide enough context to find what changed when tests fail during a refactor. I found it helpful to capture some lines from the stack trace when each query is being executed and have them accessible during test runs that use &lt;code&gt;CaptureQueriesContext&lt;&#x2F;code&gt; to be logged along with the query, when count assertions fail.&lt;&#x2F;p&gt;</summary>
        
    </entry>
    <entry xml:lang="en">
        <title>Emacs Polymode for Pico PIO files</title>
        <published>2021-02-25T00:00:00+00:00</published>
        <updated>2021-02-25T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Beshr Kayali Reinholdsson
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://log.beshr.com/emacs-polymode-pi-pico/"/>
        <id>https://log.beshr.com/emacs-polymode-pi-pico/</id>
        
        <summary type="html">&lt;p&gt;Polymode is an emacs package that provides a framework to mix multiple major modes together with a few lines of code. This can be useful when working with files that contain multiple programming languages and you&#x27;d like major mode to switch based on a matching code block for example.&lt;&#x2F;p&gt;</summary>
        
    </entry>
    <entry xml:lang="en">
        <title>This is the log.</title>
        <published>2021-02-20T00:00:00+00:00</published>
        <updated>2021-03-15T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Beshr Kayali Reinholdsson
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://log.beshr.com/thelog/"/>
        <id>https://log.beshr.com/thelog/</id>
        
        <summary type="html">&lt;p&gt;Initial post.&lt;&#x2F;p&gt;</summary>
        
    </entry>
</feed>
