<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
<title>articles.inqk.net</title>
<subtitle>Usually more extended thoughts by Michael Camilleri.</subtitle>
<link rel="alternate" type="text/html" href="https://articles.inqk.net" />
<link rel="self" type="application/atom+xml" href="https://articles.inqk.net/feed.xml" />
<id>https://articles.inqk.net/feed.xml</id>
<updated>2026-06-27T08:39:59+09:00</updated>
<rights>http://unlicense.org</rights>

<entry>
  <title>Introducing Listless</title>
  <link rel="alternate" type="text/html" href="https://articles.inqk.net/2026/04/21/introducing-listless.html" />
	<id>tag:articles.inqk.net,2026-04-21:introducing-listless</id>
	<published>2026-04-21T12:53:37+09:00</published>
	<updated>2026-04-21T14:54:52+09:00</updated>
	<author>
		<name>Michael Camilleri</name>
	</author>
	<summary type="text">An announcement post about Listless, a to-do list app for Apple platforms made using LLM-based coding agents.</summary>
	<content type="html" xml:base="https://articles.inqk.net" xml:lang="en">
    <![CDATA[
    <p><a href="https://apps.inqk.net/listless" title="Visit the official website for Listless">Listless</a> is an intentionally minimal to-do list app for Apple platforms. It is limited to one list that’s synced across your devices. Items have a title, a position in the list and a completed status. It’s free of charge and <a href="https://github.com/pyrmont/listless" title="Visit the Listless repository on GitHub">open source</a>.</p>
<p>And I typed almost none of it.</p>
<h2>Rationale</h2>
<p>Yes, this is <em>another</em> blog post about what it’s like to use LLM-based coding agents. Yes, this would have been more timely two months ago. Since I’ve already taken my time, let me put things into the appropriate context by explaining my rationale first.</p>
<h3>Do Next</h3>
<p>The first reason I made Listless is that I wanted a ‘do next’ app.</p>
<p>Apple’s Reminders is the primary repository for my to-do lists. But I’ve always found it productive to have a place where I write—and crucially prioritise—the stuff I want to accomplish in the extremely short term (i.e. today or this weekend). This is my ‘do next’ list. It’s not something I want to keep around and slowly work through. It’s an aid to help me stay focused in the moment.</p>
<p>For years, I used the excellent <a href="https://www.useclear.com/">Clear</a> to fill this need. Clear was (and still is) a to-do list app oriented around gestures. When it launched in 2012, it included iCloud sync between iPhone, iPad and the Mac. After going dormant for a few years, <a href="https://techcrunch.com/2024/01/08/an-original-app-store-innovator-clear-relaunches-its-swipeable-to-do-list-app-with-in-app-perks/">it relaunched in 2024</a> with a new business model that required a subscription for iCloud syncing. I’m not philosophically opposed to subscription pricing but something about losing access to a capability that I previously had rubbed me the wrong way.</p>
<h3>Polished Slop</h3>
<p>The second reason to make Listless is that I wanted to see whether you could use a coding agent to create a polished app. A hallmark of indie software for Apple’s platforms has been its <em>niceness</em>. I grew up using Windows and didn’t switch to the Mac until 2010. Like other long-time Windows users who switched to the Mac (Marco Arment, Casey Liss, Ben Thompson), I noticed that despite Windows having the reputation for the most software, if you cared about nice software, it was no contest: the Mac won easily.</p>
<p>Some would argue the niceness of Mac software has been in decline for years now thanks to the inexorable rise of Electron-based apps. Me. I would argue that. And you know, perhaps it’s untenable for a company to justify bespoke native apps (especially for the Mac) when a tool like Electron exists. It’s just business.</p>
<p>But what if you’re an individual and not a company? What if it isn’t just business? What if it is in fact just a hobby? AppKit, and the Cocoa family of APIs, were renowned for the incredible leverage they provided small development teams. Could coding agents increase the size of that lever still further?</p>
<p>But large language models are incredible slop-generation machines. I’m talking about using them to make <em>nice</em> software. Aren’t those things mutually exclusive? I didn’t know. Are they? I wanted to find out.</p>
<h2>Reality</h2>
<p>So in February of this year, I started a new project. Well, a sort of new project. The truth is that I’d tried to make a similar to-do list app a few years prior and it hadn’t gone well. Back then, I’d made the iPhone version with SwiftUI and it hadn’t worked well. But SwiftUI was more mature now. Maybe the promise of a cross-platform UI framework had been realised.</p>
<h3>Mac-First</h3>
<p>Still, since it was critical for my purposes that I be able to use the app on my iPhone, my iPad and my Mac, I started with the macOS version (the platform with the weakest SwiftUI support).</p>
<p>Very quickly, I had something that ‘worked’ in the loosest possible sense of the word. I could add things to a list. Then I could mark the items as completed or not. Eventually, I got reordering functional. I struggled to get SwiftUI to work well with standard Mac user interaction paradigms for text fields (e.g. the insertion point when you click on text should be at the point clicked, not at the end of the text). In the end, I opted for a <code>NSViewRepresentable</code> hosting view into which I could put a traditional <code>NSTextField</code>.</p>
<p>I got so frustrated that at one point, I decided to make the app in good old-fashioned AppKit. Even with Claude Code’s help, I struggled to literally get a window to open (I am not exaggerating for effect). SwiftUI on the Mac is rough but I decided it was preferable.</p>
<p>Eventually, it felt like the Mac version could be made to be… well, maybe not as nice as I might have hoped but at least decent. And that felt like something of an achievement. I’ve only made <a href="https://apps.inqk.net/flext">one app</a> for Apple’s platforms before Listless and I abandoned the Mac version after struggling to get anything halfway passable. This was better than that.</p>
<p>I still hadn’t typed in any code.</p>
<h3>SwiftUI Wrestling</h3>
<p>I started on the iOS version and found myself fighting with SwiftUI in new ways. I suspected from the previous attempt that implementing a gesture-centric user interface would be a challenge. SwiftUI comes with numerous ‘semantic’ view objects (e.g. <code>List</code>) and in my experience if you stick to them, things work well. As soon as you try to do something that isn’t built in, you step into the World of Pain™.</p>
<p>Are gestures that important? For me they are. As noted above, Listless is my ‘do next’ app. It’s a way for me to quickly write-up a list of tasks to do. I fell in love with Clear because of the ability to create, reorder, complete and delete in simple gestures. If Listless couldn’t do that, well, why not just create a new ‘Do Next’ list in Reminders?</p>
<p>With <code>List</code> not suitable for my needs, I began the frustrating process of recreating it using trusty old <code>ForEach</code> and <code>ScrollView</code>. This is the point at which, had I not been doing this with a coding agent, I’m confident I would have given up.<span class="connector">&#65279;<sup class="footnote-ref"><a href="#fn1" id="fnref1">1</a></sup></span> It was still exasperting at points. The most difficult aspect was getting the animation to look correct where pulling down when at the top of the list. When a user does this a new row is ‘revealed’ above the currently topmost row. At one especially low point, I almost abandoned the entire effort after discovering that the solution I had pieced together over a week or so was completely broken in iOS 26. (Thanks Liquid Glass!)</p>
<p>But I persevered. I tried to exhaust the patience of <a href="https://github.com/sogaiu" title="Visit @sogaiu's profile on GitHub">@sogaiu</a> and Eugenia (I did not succeed and am extremely grateful for all their help). I did actually type a few things (mainly integer values as I tweaked the responsiveness of certain things). I got something that I think is all right. It’s not as polished as it could be but I don’t think it’s slop either.<span class="connector">&#65279;<sup class="footnote-ref"><a href="#fn2" id="fnref2">2</a></sup></span></p>
<h2>Final Thoughts</h2>
<p>Did I succeed in my goal? I think I did. The code is <a href="https://github.com/pyrmont/listless" title="Visit the Listless repository on GitHub">open source</a> so you can judge for yourself. In a little over two months I made an app that runs on iOS, iPadOS, watchOS and macOS. Having overcome the frustrations of SwiftUI development, I feel like I came out the other side thanks in no small part to Claude Code and OpenAI Codex. I feel empowered and I’m excited for what I will create next.</p>
<section class="footnotes">
<ol>
<li id="fn1">
<p>Honestly, if I’d really been programming by hand, I almost certainly would have admitted defeat trying to implement the insertion point thing on the Mac. <a href="#fnref1" class="footnote-backref">↩</a></p>
</li>
<li id="fn2">
<p>Version 1.2.1 of Listless has an animation hitch that I see on my iPhone 14 Pro Max and which I consider needs to be fixed. I can recreate the issue reliably by doing a quick pull-down-to-create gesture from a cold start. Claude hypothesises that this is because the iOS version also uses a hosted view for the text field (<code>UIViewRepresentable</code> in its case) and that creating the UIKit objects and putting them into the SwiftUI hosting view is computationally intensive.</p>
<p>I would like to instrument this more to understand exactly what’s slowing it down but I have to wait until I have an iPhone with a working connection port to do that using Apple’s tools. (At some point my Lightning port broke and the iPhone no longer recognises connections to it. Unfortunately, in order to pair an iPhone to a Mac so that you can do things like instrument debug builds of apps, you need to plug the phone into the computer by a cable.) <a href="#fnref2" class="footnote-backref">↩</a></p>
</li>
</ol>
</section>

    ]]>
  </content>
</entry>

<entry>
  <title>Introducing Jeep</title>
  <link rel="alternate" type="text/html" href="https://articles.inqk.net/2025/11/20/introducing-jeep.html" />
	<id>tag:articles.inqk.net,2025-11-20:introducing-jeep</id>
	<published>2025-11-20T08:28:37+09:00</published>
	<updated>2025-11-20T17:46:07+09:00</updated>
	<author>
		<name>Michael Camilleri</name>
	</author>
	<summary type="text">An announcement post about Jeep, a bundle manager for the Janet programming language.</summary>
	<content type="html" xml:base="https://articles.inqk.net" xml:lang="en">
    <![CDATA[
    <p>I’m excited to introduce <a href="https://github.com/pyrmont/jeep" title="Visit the GitHub repository for the Jeep project.">Jeep</a>, a bundle manager for the Janet programming
language.</p>
<p>A <em>bundle</em> is the term used in Janet to describe a distributable collection of
files. It’s akin to a package in Node, a gem in Ruby or a crate in Rust. In
v1.35.0, Janet gained the ability to install bundles without any additional
tooling. Prior to that, bundles were installed with <a href="https://github.com/janet-lang/jpm" title="Visit the GitHub repository for the JPM project.">JPM</a>, the Janet Project
Manager.</p>
<p>Jeep is built around various <em>subcommands</em>. There are global subcommands that
can be used anywhere (e.g. <code>jeep install</code>, <code>jeep uninstall</code>) and local
subcommands that are run in the bundle root of a bundle (e.g. <code>jeep build</code>,
<code>jeep prepare</code>).</p>
<p>Now I think Jeep is cool but if you didn’t develop it, you might reasonably
have some questions about why you would want to use it. The remainder of this
introduction is structured as a series of questions and answers.</p>
<h3>Q. If Janet can install bundles, what is the point of Jeep?</h3>
<p>While Janet can install bundles, there are two key limitations:</p>
<ol>
<li>Janet does not include any machinery to download remote bundles. You need to
do that yourself.</li>
<li>Janet checks whether the dependencies of a bundle are installed but it
doesn’t download and install them for you.</li>
</ol>
<p>Jeep comes with an <code>install</code> subcommand that will install a bundle, together
with any external dependencies that are listed in the bundle’s info file.</p>
<h3>Q. If JPM can install bundles, what is the point of Jeep?</h3>
<p>JPM can install legacy bundles (i.e. bundles that use a <code>project.janet</code> file)
but it cannot install modern bundles (i.e. bundles that use an <code>info.jdn</code>
file).<span class="connector">&#65279;<sup class="footnote-ref"><a href="#fn1" id="fnref1">1</a></sup></span></p>
<h3>Q. Why do I want to use modern bundles?</h3>
<p>Legacy bundles continue to work fine and there’s no reason you <em>have</em> to
change. For me, modern bundles are preferable for two reasons:</p>
<ol>
<li>Modern bundles aren’t tied to a particular tool. Once they’re on the file
system, Janet can install them. Legacy bundles works today but they depend
on JPM. JPM itself lacks robust tests and its heavy use of <code>use</code> can make it
difficult to read.</li>
<li>Modern bundles cleanly separate metadata (listed in a bundle’s info file)
from management logic (listed in the bundle’s bundle script). This makes it
easier for other tools to extract information from your bundle without
needing to run any code. In addition, since the management logic is in your
bundle script and Janet, you’re not tied to one particular bundle manager
(even Jeep!).</li>
</ol>
<h3>Q. Can I use Jeep to install legacy bundles?</h3>
<p>No. I realise this might reasonably be a deal breaker for many people. If you
are installing a modern bundle but it depends on a legacy bundle, Jeep cannot
install it. janet-pm (discussed below) does not have this limitation.</p>
<h3>Q. Are there any alternatives?</h3>
<p>Apart from JPM, the only other alternative at the time of writing is janet-pm.
janet-pm is part of the <a href="https://github.com/janet-lang/spork" title="Visit the GitHub repository for the Spork project.">Spork</a> library, the official contrib library (and
one that many people install). janet-pm makes a best effort to install legacy
bundles and so can be a good solution for someone who wants one tool to support
both legacy and modern bundles.</p>
<h3>Q. What are some cool things you can do in Jeep?</h3>
<p>A few of the interesting subcommands:</p>
<ul>
<li>
<p><code>jeep api</code>: This subcommand creates <code>api.md</code>, a Markdown file in your bundle
root that lists the function signatures and docstrings for the functions
exposed by your bundle’s modules.</p>
</li>
<li>
<p><code>jeep list</code>: This subcommand lists information about your current Janet
environment. This includes the bundles you have installed, the version of
Janet you are running and relevant environment variables.</p>
</li>
<li>
<p><code>jeep test</code>: This subcommand runs the Janet files that are in <code>./test</code> similar
to how <code>jpm test</code> works. Unlike JPM, Jeep can run specific files using the
<code>-f</code> option for situations where you don’t need to run the entire suite.</p>
</li>
</ul>
<h3>Q. How can I learn more about Jeep’s subcommands?</h3>
<p>Jeep includes a rich suite of man pages that describe its features. You can
read them by typing <code>jeep help &lt;subcommand&gt;</code> at the command line. For those
who’d like to see what Jeep can offer before installation, the pages are
written in <a href="https://pyrmont.github.io/pyrmont" title="Visit the official Predoc website.">Predoc</a>, a Markdown flavour that I developed. As Markdown,
they’re readable as plain text right in the <a href="https://github.com/pyrmont/jeep/tree/master/man/man1" title="See a listing of the manpages in the GitHub repository.">GitHub repository</a>.</p>
<h3>Q. Is there some way I can convert a legacy bundle into a modern bundle?</h3>
<p>Yes. Jeep’s <code>enhance</code> subcommand can be run in the bundle root of a legacy
bundle and it will attempt to create the files for a modern bundle while
preserving the metadata encoded in the legacy bundle’s <code>project.janet</code>.</p>
<hr />
<p>Do you have more questions? Feel free to open an issue in the <a href="https://github.com/pyrmont/jeep/issues" title="Visit the Issues section of the GitHub repository for the Jeep proejct.">Issues
section</a> of the GitHub repository.</p>
<section class="footnotes">
<ol>
<li id="fn1">
<p>At least at the time of writing. <a href="#fnref1" class="footnote-backref">↩</a></p>
</li>
</ol>
</section>

    ]]>
  </content>
</entry>

<entry>
  <title>Recommended Directory Structure for Janet&apos;s Modern Bundles</title>
  <link rel="alternate" type="text/html" href="https://articles.inqk.net/2025/09/18/revised-janet-dir-structure.html" />
	<id>tag:articles.inqk.net,2025-09-18:revised-janet-dir-structure</id>
	<published>2025-09-18T17:07:37+09:00</published>
	<updated>2025-09-18T19:53:55+09:00</updated>
	<author>
		<name>Michael Camilleri</name>
	</author>
	<summary type="text">A revised recommended directory structure for use by Janet bundle authors.</summary>
	<content type="html" xml:base="https://articles.inqk.net" xml:lang="en">
    <![CDATA[
    <p><strong><em>In January 2025, <a href="https://articles.inqk.net/2025/01/09/janet-dir-structure.html" title="Read
the article 'Recommended Directory Structure for Janet Packages'.">I recommended a directory structure</a> for what I
would now call Janet’s legacy bundles<span class="connector">&#65279;<sup class="footnote-ref"><a href="#fn1" id="fnref1">1</a></sup></span>. This post is a revised version
for modern bundles.</em></strong></p>
<p>I like making bundles for the Janet programming language. I also like things to
be neat and consistent. This has led to me spending too much time thinking about
a directory structure I can use for Janet bundles.</p>
<p>For a bundle called <code>&lt;bundle&gt;</code><span class="connector">&#65279;<sup class="footnote-ref"><a href="#fn2" id="fnref2">2</a></sup></span>, here’s what I’ve come up with:</p>
<pre class="code highlight language-txt"><code><span class="line-1">&lt;bundle&gt;
</span><span class="line-2">├─ bin/
</span><span class="line-3">├─ bundle/
</span><span class="line-4">│  └─ init.janet
</span><span class="line-5">├─ deps/
</span><span class="line-6">├─ lib/
</span><span class="line-7">├─ res/
</span><span class="line-8">├─ src/
</span><span class="line-9">├─ test/
</span><span class="line-10">├─ info.jdn
</span><span class="line-11">├─ init.janet
</span><span class="line-12">├─ LICENSE
</span><span class="line-13">└─ README.md
</span></code></pre>
<p>To explain:</p>
<ul>
<li><code>bin/</code>: This directory contains the binscripts<span class="connector">&#65279;<sup class="footnote-ref"><a href="#fn3" id="fnref3">3</a></sup></span> that your bundle will
install. In <a href="https://github.com/pyrmont/lemongrass" title="Visit the GitHub repository for the
Lemongrass bundle.">Lemongrass</a>, for example, I provide a CLI utility, <code>lg</code>,
that is installed as part of the bundle.</li>
</ul>
<ul>
<li><code>bundle/</code>: This directory contains your bundle script (<code>init.janet</code>) and any
helper scripts necessary for managing your bundle. In <a href="https://github.com/pyrmont/predoc" title="Visit the GitHub repository for the
Predoc bundle.">Predoc</a>, for
example, I include a bunch of files from the <a href="https://github.com/janet-lang/spork" title="Visit the GitHub repository for the
Spork bundle.">Spork</a> library so that you
can compile the <code>predoc</code> binary without anything other than the <code>janet</code>
binary.<span class="connector">&#65279;<sup class="footnote-ref"><a href="#fn4" id="fnref4">4</a></sup></span></li>
</ul>
<ul>
<li><code>deps/</code>: This directory contains vendored dependencies that your bundle uses.
I’ve moved to using vendored dependencies as a way to avoid some of the issues
that arise when you’re trying to share dependencies across all bundles. If
that sounds interesting, check out my bundle manager <a href="https://github.com/pyrmont/jeep" title="Visit the GitHub repository for the Jeep
bundle.">Jeep</a>. It makes
vendoring dependencies as easy as can be.</li>
</ul>
<ul>
<li>
<p><code>lib/</code>: This directory contains the Janet code that is used in your bundle.</p>
</li>
<li>
<p><code>res/</code>: This directory contains resources (images, testing fixtures, helper
scripts) that are used by your bundle.</p>
</li>
<li>
<p><code>src/</code>: This directory contains code (typically C code) that is compiled for
use in your bundle.</p>
</li>
<li>
<p><code>test/</code>: This directory contains tests for your bundle. If you’re using a
bundle manager like Jeep it comes with a <code>jeep test</code> command that runs all the
tests in the <code>test</code> directory.</p>
</li>
<li>
<p><code>info.jdn</code>: This file contains metadata about your bundle written as a struct
or table in Janet Data Notation (or JDN). The only mandatory key is <code>:name</code>
but you can include other information that might be useful to your bundle
script or to consumers of your bundle.</p>
</li>
<li>
<p><code>init.janet</code>: This file allows a consumer of your bundle to import the top
level bindings by simply writing <code>(import &lt;bundle&gt;</code>) in their Janet file.
This is because <code>init.janet</code> is a ‘magic file’ that Janet’s module loader
looks for when it tries to resolve an import call. So using Lemongrass as an
example again, a consumer of the bundle can write:</p>
<pre class="code highlight language-janet"><code><span class="line-1"><span class="p">(</span><span class="kr">import</span><span class="w"> </span><span class="n">lemongrass</span><span class="w"> </span><span class="kc">:as</span><span class="w"> </span><span class="n">lg</span><span class="p">)</span>
</span><span class="line-2">
</span><span class="line-3"><span class="p">(</span><span class="nf">lg/markup-&gt;janet</span><span class="w"> </span><span class="s2">"&lt;p&gt;Hello world&lt;/p&gt;"</span><span class="p">)</span>
</span></code></pre>
<p>This works even though the <code>mark-up-&gt;janet</code> function is defined in
<code>lib/to-janet.janet</code> because <code>init.janet</code> imports this module file and then
exports its bindings.</p>
</li>
<li>
<p><code>LICENSE</code>: The licence that you apply to your bundle.</p>
</li>
<li>
<p><code>README.md</code>: Your README in Markdown format.</p>
</li>
</ul>
<p>If your bundle doesn’t need any of the above directories, feel free to leave it
out.</p>
<p>I’ve been using this structure for the last six months or so and have found it
works well. I hope others find it helpful, too!</p>
<section class="footnotes">
<ol>
<li id="fn1">
<p>This post uses terminology like <em>legacy bundle</em> and <em>modern bundle</em>
that I introduced in <a href="https://articles.inqk.net/2025/09/15/janet-bundles.html" title="Read the article
'Bundles in Janet'.">this post</a>. <a href="#fnref1" class="footnote-backref">↩</a></p>
</li>
<li id="fn2">
<p>Because of how Janet works internally, bundles should not be called
‘bin’, ‘bundle’ or ‘man’. <a href="#fnref2" class="footnote-backref">↩</a></p>
</li>
<li id="fn3">
<p>A <em>binscript</em> is a text file that is marked executable and begins with
<code>#!/usr/bin/env janet</code>. This will cause the OS to run the Janet code in the file
through the <code>janet</code> binary installed on the user’s system. <a href="#fnref3" class="footnote-backref">↩</a></p>
</li>
<li id="fn4">
<p>Seriously, just clone the repo, <code>cd</code> into the directory and then run
<code>janet -e '(import ./bundle) (bundle/build (table :info (-&gt; (slurp &quot;info.jdn&quot;) parse)))'.</code>
I think that’s pretty fab. <a href="#fnref4" class="footnote-backref">↩</a></p>
</li>
</ol>
</section>

    ]]>
  </content>
</entry>

<entry>
  <title>Bundles in Janet</title>
  <link rel="alternate" type="text/html" href="https://articles.inqk.net/2025/09/15/janet-bundles.html" />
	<id>tag:articles.inqk.net,2025-09-15:janet-bundles</id>
	<published>2025-09-15T00:44:09+09:00</published>
	<updated>2025-11-13T07:10:06+09:00</updated>
	<author>
		<name>Michael Camilleri</name>
	</author>
	<summary type="text">Suggested terminology for concepts related to Janet's bundles.</summary>
	<content type="html" xml:base="https://articles.inqk.net" xml:lang="en">
    <![CDATA[
    <p>I’m currently working on <a href="https://github.com/pyrmont/jeep">Jeep</a>, a bundle manager for the Janet
programming language. As you might expect, I’ve had to learn quite a bit about
how bundles work in Janet. One of the things that I’ve struggled with is what to
call various aspects. In this post, I want to describe some of the concepts and
suggest some terminology for the Janet community to consider using.</p>
<h2>Bundle</h2>
<p>A <em>bundle</em> is Janet’s term for what some languages call a package. At its most
basic, a bundle:</p>
<ul>
<li>is a directory of files that can contain Janet code, documentation and other
resources; and</li>
<li>is installable.</li>
</ul>
<p>Making a directory isn’t that difficult but how do you make something
‘installable’?</p>
<h3>Bundle Types</h3>
<p>Unfortunately, for historical reasons, Janet has two types of bundles.</p>
<p>First, there are <strong>legacy bundles</strong>.<span class="connector">&#65279;<sup class="footnote-ref"><a href="#fn1" id="fnref1">1</a></sup></span> A legacy bundle is made installable
by the presence of a file titled <code>project.janet</code> in the <em>bundle root</em>. Legacy
bundles were developed to work with the Janet Project Manager (commonly
referred to as <code>jpm</code>). A legacy bundle cannot be installed by the <code>janet</code>
binary alone.<span class="connector">&#65279;<sup class="footnote-ref"><a href="#fn2" id="fnref2">2</a></sup></span></p>
<p>Second, there are <strong>modern bundles</strong>.<span class="connector">&#65279;<sup class="footnote-ref"><a href="#fn3" id="fnref3">3</a></sup></span> A modern bundle is made installable
by the presence of an <em>info file</em> and a <em>bundle script</em>.<span class="connector">&#65279;<sup class="footnote-ref"><a href="#fn4" id="fnref4">4</a></sup></span> Once you get a
bundle on the local file system, it can be installed by the <code>janet</code> binary
alone.</p>
<p>It is possible for a bundle to be <em>both</em> a legacy bundle and a modern bundle if
the bundle includes all the necessary files (a <code>project.janet</code> file, an info
file and a bundle script).</p>
<h2>Artifacts</h2>
<p>Saying that a bundle is ‘installable’ really means that it has <em>artifacts</em> that
can be installed. Janet has built-in support for installing and uninstalling
artifacts from modern bundles. The <code>janet</code> binary cannot install artifacts from
legacy bundles without an additional tool.</p>
<p>Installing a bundle means copying one or more of the following artifacts into
the <em>syspath</em>:</p>
<ol>
<li>a <strong>module file</strong> in Janet</li>
<li>an <strong>executable file</strong> in Janet</li>
<li>a <strong>compiled module file</strong> in machine code</li>
<li>a <strong>compiled executable file</strong> in machine code</li>
<li>a <strong>man page file</strong></li>
</ol>
<p>Uninstalling means removing the files that were copied.</p>
<p>When installing a modern bundle, Janet creates a <em>manifest</em> that, among other
things, lists all of the paths that were created during installation. As a
result, Janet can make sure those paths are removed when the bundle is
uninstalled.</p>
<h2>syspath</h2>
<p>In Janet, the <em>syspath</em> is a special directory on the file system where Janet
will install artifacts, save bundle data<span class="connector">&#65279;<sup class="footnote-ref"><a href="#fn5" id="fnref5">5</a></sup></span> and (perhaps most important)
look for modules to load.</p>
<p>On POSIX systems, the default syspath is:</p>
<ul>
<li><code>/usr/local/lib/janet</code></li>
</ul>
<p>If installed via Homebrew, it is:</p>
<ul>
<li><code>/opt/homebrew/lib/janet</code></li>
</ul>
<p>While on Windows, the default syspath is:</p>
<ul>
<li><code>%APPDATA%\Janet\Library</code></li>
</ul>
<p>Inside the syspath are three reserved directories:</p>
<ul>
<li><code>&lt;syspath&gt;/bin</code></li>
<li><code>&lt;syspath&gt;/bundle</code></li>
<li><code>&lt;syspath&gt;/man</code></li>
</ul>
<p>These are discussed below.</p>
<h2>Manifest</h2>
<p>The <em>manifest</em> is a collection of metadata concerning an installed bundle. It
is created during the installation process by Janet and saved in
<code>&lt;syspath&gt;/bundle/&lt;bundle-name&gt;/manifest.jdn</code>.</p>
<h2>Bundle Root</h2>
<p>I use the term <em>bundle root</em> to refer to the top-level of the bundle itself.
Where paths in this article are of the form <code>./foo.bar</code>, this refers to a file
called <code>foo.bar</code> that is at the top-level of the bundle (i.e. the bundle root).</p>
<p>Janet does not mandate a structure for the bundle but, as noted above, modern
bundles should contain an info file and a bundle script.</p>
<h2>Info File</h2>
<p>The <em>info file</em> is a text file written in JDN (Janet data notation). The info
file can be located in one of two places relative to the bundle root:</p>
<ol>
<li><code>./bundle/info.jdn</code></li>
<li><code>./info.jdn</code>.</li>
</ol>
<p>The file must describe a single data structure, either a struct or table, that
maps the key <code>:name</code> to a string value that represents the name of the bundle.
Note that the name of the bundle is used as the name of the subdirectory within
<code>&lt;syspath&gt;/bundle</code> directory. For this reason, two bundles cannot be installed
with the same name.</p>
<p>The info file should also list the external dependencies of the bundle (if any).
This information is stored as an array/tuple that is associated with the key
<code>:dependencies</code> at the top-level of the data structure. During the installation
process, Janet will confirm that the dependencies listed are installed before
proceeding with installation.</p>
<p>Here’s an example of an info file:</p>
<pre class="code highlight language-janet"><code><span class="line-1"><span class="p">{</span><span class="kc">:name</span><span class="w"> </span><span class="s2">"foo"</span>
</span><span class="line-2"><span class="w"> </span><span class="kc">:version</span><span class="w"> </span><span class="s2">"1.0.0"</span>
</span><span class="line-3"><span class="w"> </span><span class="kc">:description</span><span class="w"> </span><span class="s2">"Just adds all the foo"</span>
</span><span class="line-4"><span class="w"> </span><span class="kc">:author</span><span class="w"> </span><span class="s2">"A Programmer"</span>
</span><span class="line-5"><span class="w"> </span><span class="kc">:license</span><span class="w"> </span><span class="s2">"MIT"</span>
</span><span class="line-6"><span class="w"> </span><span class="kc">:url</span><span class="w"> </span><span class="s2">"https://example.org/foo"</span>
</span><span class="line-7"><span class="w"> </span><span class="kc">:repo</span><span class="w"> </span><span class="s2">"git+https://example.org/foo"</span>
</span><span class="line-8"><span class="w"> </span><span class="kc">:dependencies</span><span class="w"> </span><span class="p">[{</span><span class="kc">:name</span><span class="w"> </span><span class="s2">"bar"</span>
</span><span class="line-9"><span class="w">                 </span><span class="kc">:url</span><span class="w"> </span><span class="s2">"https://example.org/bar"</span><span class="p">}]</span>
</span><span class="line-10"><span class="w"> </span><span class="kc">:artifacts</span><span class="w"> </span><span class="p">{</span><span class="kc">:libraries</span><span class="w"> </span><span class="p">[{</span><span class="kc">:prefix</span><span class="w"> </span><span class="s2">"foo"</span>
</span><span class="line-11"><span class="w">                          </span><span class="kc">:paths</span><span class="w"> </span><span class="p">[</span><span class="s2">"init.janet"</span>
</span><span class="line-12"><span class="w">                                  </span><span class="s2">"lib"</span><span class="p">]}]</span>
</span><span class="line-13"><span class="w">             </span><span class="kc">:manpages</span><span class="w"> </span><span class="p">[</span><span class="s2">"man/man1/foo.1"</span><span class="p">]</span>
</span><span class="line-14"><span class="w">             </span><span class="kc">:scripts</span><span class="w"> </span><span class="p">[{</span><span class="kc">:path</span><span class="w"> </span><span class="s2">"bin/foo"</span><span class="p">}]}}</span>
</span></code></pre>
<p>In addition to <code>:name</code> and <code>:dependencies</code>, this example includes several other
keys. Some of these, like <code>:description</code>, are more for communicating to the
potential consumer. Some, like <code>:artifacts</code> , may be used by a particular
bundle script.<span class="connector">&#65279;<sup class="footnote-ref"><a href="#fn6" id="fnref6">6</a></sup></span></p>
<h2>Bundle Script</h2>
<p>The <em>bundle script</em> is a text file containing Janet code. The bundle script can
be located in one of two places relative to the bundle root:</p>
<ol>
<li><code>./bundle/init.janet</code></li>
<li><code>./bundle.janet</code></li>
</ol>
<p>As discussed below, the bundle script contains functions that will be called
during the installation and uninstallation process.</p>
<p>It is important to note that, before any functions are called, the info file
and bundle script are copied to <code>&lt;syspath&gt;/bundle</code>. Both files are placed
inside a subdirectory with the same name as the bundle (i.e.
<code>&lt;syspath&gt;/bundle/&lt;bundle-name&gt;</code>). Janet in fact copies all files from the
bundle’s <code>./bundle</code> directory to <code>&lt;syspath&gt;/bundle/&lt;bundle-name&gt;</code>.</p>
<p>As a result, a bundle script can import other modules but it <strong>should not</strong> do
this relative to directories in the bundle root since at the time of
evaluation, the bundle script will be located in
<code>&lt;syspath&gt;/bundle/&lt;bundle-name&gt;</code>. If a user’s bundle script depends on modules,
these should be imported from the syspath:</p>
<pre class="code highlight language-janet"><code><span class="line-1"><span class="p">(</span><span class="kr">import</span><span class="w"> </span><span class="n">foo</span><span class="p">)</span>
</span></code></pre>
<p>or they should be included in the bundle’s <code>./bundle</code> directory and then imported
relative to the bundle script:</p>
<pre class="code highlight language-janet"><code><span class="line-1"><span class="p">(</span><span class="kr">import</span><span class="w"> </span><span class="n">./foo</span><span class="p">)</span>
</span></code></pre>
<p>You can see an example of doing this in the <a href="https://github.com/pyrmont/predoc/blob/ad43c7b3e48b65111fd95c62f604910791c5a10f/bundle/init.janet">bundle script</a> for Predoc, my
tool for generating man pages.</p>
<h2>Bundle Hooks</h2>
<p>Janet deliberately leaves the logic for installing artifacts to the bundle
author. It does this by using <em>bundle hooks</em>. A bundle author can think of a
bundle hook as a call to an identically named function in the bundle’s bundle
script.</p>
<p>Janet calls up to five hooks during the installation process:</p>
<ol>
<li><code>postdeps</code><span class="connector">&#65279;<sup class="footnote-ref"><a href="#fn7" id="fnref7">7</a></sup></span></li>
<li><code>clean</code> (optional)</li>
<li><code>build</code></li>
<li><code>install</code></li>
<li><code>check</code> (optional)</li>
</ol>
<p>The optional hooks are only called if specified in an argument to
<code>bundle/install</code>.</p>
<p>One hook is called during the uninstallation process:</p>
<ol>
<li><code>uninstall</code></li>
</ol>
<p>As noted above, each bundle hook effectively calls an identically named
function in the bundle script. The function is called with the data in the
manifest as its first argument. This importantly includes the information in
the info file under the <code>:info</code> key.</p>
<p>If a bundle author doesn’t define a function for a particular hook, nothing
happens and Janet moves onto the next hook. Some bundles don’t need a build
step, for example, and so can simply not define a <code>build</code> function. Others may
not need a <code>postdeps</code> function.</p>
<p>Every bundle script should include an <code>install</code> function and this function
should make calls to some combination of <code>bundle/add</code>, <code>bundle/add-directory</code>,
<code>bundle/add-bin</code> and <code>bundle/add-manpage</code> to copy various artifacts into the
syspath. Using these functions ensures that the paths created are saved in the
manifest and so can be properly removed during the uninstallation process.</p>
<h2>Conclusion</h2>
<p>Janet bundles are still a bit of a work in progress and the suggested terms here
are just that: suggestions. If you have questions, the <a href="https://github.com/janet-lang/janet">GitHub repository</a>
is a good place to ask.</p>
<section class="footnotes">
<ol>
<li id="fn1">
<p>This is my term of art. Use it at parties to sound cool. <a href="#fnref1" class="footnote-backref">↩</a></p>
</li>
<li id="fn2">
<p>Legacy bundles are not a focus of Jeep and so are not discussed further
in this article. More information about legacy bundles is available on the
<a href="https://janet-lang.org/jpm/">Janet website</a>. <a href="#fnref2" class="footnote-backref">↩</a></p>
</li>
<li id="fn3">
<p>Again, sound cool at parties. <a href="#fnref3" class="footnote-backref">↩</a></p>
</li>
<li id="fn4">
<p>Strictly speaking, you can install bundles without these files but this
isn’t documented at the time of writing and I think it is simpler to treat these
files as being required. <a href="#fnref4" class="footnote-backref">↩</a></p>
</li>
<li id="fn5">
<p>The bundle manifest, the info file and the bundle script. <a href="#fnref5" class="footnote-backref">↩</a></p>
</li>
<li id="fn6">
<p>Bundle scripts generated by Jeep look for this key to determine which
artifacts to install. <a href="#fnref6" class="footnote-backref">↩</a></p>
</li>
<li id="fn7">
<p>Previously <code>dependencies</code>. <a href="#fnref7" class="footnote-backref">↩</a></p>
</li>
</ol>
</section>

    ]]>
  </content>
</entry>

<entry>
  <title>Podcasts I&apos;m Listening To: Spring 2025</title>
  <link rel="alternate" type="text/html" href="https://articles.inqk.net/2025/05/31/podcasts-spring-2025.html" />
	<id>tag:articles.inqk.net,2025-05-31:podcasts-spring-2025</id>
	<published>2025-05-31T23:12:37+09:00</published>
	<updated>2025-07-12T17:11:08+09:00</updated>
	<author>
		<name>Michael Camilleri</name>
	</author>
	<summary type="text">A listing of the podcasts I’m listening to in spring of 2025.</summary>
	<content type="html" xml:base="https://articles.inqk.net" xml:lang="en">
    <![CDATA[
    <p>This is my eighth year of annually<span class="connector">&#65279;<sup class="footnote-ref"><a href="#fn1" id="fnref1">1</a></sup></span> listing the podcasts I’m listening to. As the title says, this is meant to come out in spring but this year I’m writing it well into summer, though<span class="connector">&#65279;<sup class="footnote-ref"><a href="#fn2" id="fnref2">2</a></sup></span>; forgive me.</p>
<p>As with previous entries, the list is broken down into ‘Currently Subscribed’ and ‘Previously Subscribed’ sections. If a podcast came into and went out of rotation within the last 12 months it still goes in ‘Previously Subscribed’. Podcasts that are new to the list are in bold and paid podcasts are marked with a 💰 emoji.</p>
<p>Happy listening!</p>
<h2>Currently Subscribed</h2>
<ul>
<li>
<p><a href="https://www.theringer.com/22-goals">22 Goals</a>: I <em>finally</em> succeeded in getting a friend to listen to at least one episode of this show. It remains my favourite podcast.</p>
</li>
<li>
<p><a href="https://atp.fm/">Accidental Tech Podcast</a> 💰: I said last year that while this is still the premier Apple podcast, it had fallen off since the glory years of the late 2010s. That’s true but it does still occasionally hit those highs. There’s exactly one podcast that made me laugh out loud as I walked down the streets of Urayasu on a balmy summer night in June 2024 and it was ATP. (I’ve added a 💰 this year because although you don’t have to pay for the show, I do.)</p>
</li>
<li>
<p><a href="https://atrpodcast.com/">Against the Rules</a>: Michael Lewis’ podcast about modern American life took a hard look at the rise of legalised sportsbetting in the United States. After the letdown of the season that accompanied Lewis’ <em>Going Infinite</em>, this was a welcome return to form.</p>
</li>
<li>
<p><a href="https://stratechery.com/stratechery-plus/"><strong>Asianometry</strong></a> 💰: This podcast was added to the stable of podcasts available to subscribers to Ben Thompson’s Stratechery Plus. In it, host Jon Yu puts audio recordings of the episodes from his <a href="https://www.youtube.com/@Asianometry">Asianometry YouTube channel</a>. These tend to be explainers about certain aspects of materials science  that have a connection to Asia (especially related to the semiconductor industry) but Yu isn’t afraid of venturing further afield.</p>
</li>
<li>
<p><a href="https://sscpodcast.libsyn.com/website">Astral Codex Ten Podcast</a>: An audio version of the posts of blogger Scott Alexander. Pseudonymous host Solenoid Entity had to take a couple of weeks off over the past 12 months and I didn’t realise until he was gone how central his voice has become to my weekly routine.</p>
</li>
<li>
<p><a href="http://timharford.com/articles/cautionarytales/">Cautionary Tales</a>: Pop economist and long-time columnist for the <em>Financial Times</em> Tim Harford didn’t take my advice from last year and avoid stuffing something in his feed weekly but when you prune the filler out, the actual episodes are still great.</p>
</li>
<li>
<p><a href="https://corecursive.com">CoRecursive</a>: Programmer Adam Gordon Bell continues to find interesting stories from people in the software engineering community. By editing his conversations down into a narrated guide through each episode, the show never overstays its welcome.</p>
</li>
<li>
<p><a href="https://slate.com/podcasts/decoder-ring">Decoder Ring</a>: Willa Paskin put together another year of great essays about cultural mysteries. I complained last year that it was a shame how much filler was put into the feed cross-promoting other podcasts from Slate. I’m sad to say this has not improved.</p>
</li>
<li>
<p><a href="https://dithering.fm/">Dithering</a> 💰: Apple blogger John Gruber and tech analyst Ben Thompson’s paid podcast about technology does feel a bit worn by this point but the fact its 15-minute episodes are only twice a week helps protect it from ever feeling completely worn out.</p>
</li>
<li>
<p><a href="https://www.pushkin.fm/podcasts/fiasco"><strong>Fiasco</strong></a>: Leon Neyfakh was the original host of <em>Slow Burn</em> and I was extremely disappointed when he left to make the <em>Fiasco</em> podcast for closed-platform Luminary (and then Amazon). Fortunately, those deals have now come to an end and he’s brought <em>Fiasco</em> to the Pushkin network. The most recent series they’ve published was about Iran-Contra and it was terrific.</p>
</li>
<li>
<p><a href="https://geopolitical-cousins.captivate.fm"><strong>Geopolitical Cousins</strong></a>: Jacob Shapiro and Marko Papic are analysts who write advice for clients about geopolitics. In March 2025, they started a podcast to discuss geopolitical topics in a more casual form. If you wish more geopolitical analysis contained references to the NBA, this is the show for you.</p>
</li>
<li>
<p><a href="https://greatestofalltalk.com">Greatest of All Talk</a> 💰: As I did last year, I stopped listening to this show until around the time of the NBA Playoffs. Ben Golliver of the <em>Washington Post</em> and Andrew Sharp formerly of <em>Sports Illustrated</em> have terrific chemistry together and when I need a hit of basketball chat, this is where I go.</p>
</li>
<li>
<p><a href="https://slate.com/podcasts/hit-parade">Hit Parade</a>: I wrote last year how impressed I was at the essay Chris Molanphy writes each month. That feeling hasn’t abated and he keeps finding topics to writing about that pique my interest. If you’re remotely interested in the history of American pop music, I heartily recommend it.</p>
</li>
<li>
<p><a href="https://howtojapanese.com"><strong>How to Japanese Podcast</strong></a>: I don’t remember now how I came across this podcast but I’m glad that I did. Host Daniel Morales, a professional Japanese to English translator who lives in Osaka, records an episode each month where he riffs on some aspect of the Japanese language that was the subject of his monthly newsletter. I say ‘riff’ because while the simple thing to do would be to just read the newsletter, Morales instead uses each episode to present the same topic from a slightly different perspective.</p>
</li>
<li>
<p><a href="https://www.jacobshapiro.com/"><strong>The Jacob Shapiro Podcast</strong></a>: Jacob Shapiro describes himself on his website as ‘a geopolitical analyst who provides strategic guidance to families, investors, and corporations’. His podcast features him interviewing experts about major geopolitical issues. I don’t listen to every episode but I feel like I learn a lot when I tune in.</p>
</li>
<li>
<p><a href="https://www.vox.com/land-of-the-giants-podcast">Land of the Giants</a>: This podcast is a quasi-audio documentary about one of the giant tech (or tech-adjacent) companies that dominate our lives (the most recent season was about Disney, for example). The main thing I praised this podcast for last year was how disciplined it is about its seasons. They put episodes from the show itself in their feed and <em>nothing else</em>. More like this please.</p>
</li>
<li>
<p><a href="https://www.citationneeded.news/">Molly White’s Citation Needed</a>: Blogger Molly White records a new episode for each edition of her newsletter about A.I., cryptocurrency and the world wide web. I wish more writers would do this.</p>
</li>
<li>
<p><a href="https://www.abc.net.au/listen/programs/politics-now">The Party Room</a>: Much to my extreme frustration, this podcast about Australian federal politics was folded into an omnibus feed from the ABC featuring episodes from across its roster of political shows. So of course I did what any self-respecting programming nerd would do and created my own filtered version of the feed so that I could listen to veteran ABC presenters Patricia Karvelas and Fran Kelly in peace. That feed is <a href="https://feeds.inqk.net/the_party_room.xml">here</a> if anyone else is similarly interested.</p>
</li>
<li>
<p><a href="https://www.therepl.net/">The REPL</a>: From May 2024 until May 2025, host Daniel Compton released precisely two episodes of his podcast about Clojure. One was in September and the other in October. A totally acceptable cadence in my book!</p>
</li>
<li>
<p><a href="https://revisionisthistory.com/">Revisionist History</a>: I noticed that Malcolm Gladwell recently changed from introducing this as ‘my podcast about things overlooked and misunderstood’ to ‘my show about things overlooked and misunderstood’. I preferred the dorkier ‘podcast’.</p>
</li>
<li>
<p><a href="https://serioustrouble.show/">Serious Trouble</a>: I love the rapport between journalist Josh Barro and lawyer Ken White as they break down recent legal issues that have arisen in U.S. politics. White’s sober analysis and Barro’s incisive questioning are what makes every episode feel like time well spent.</p>
</li>
<li>
<p><a href="https://slate.com/podcasts/slow-burn">Slow Burn</a>: In 2024, the <em>Slow Burn</em> team focused on the rise of Fox News and it was another great season of six or so episodes. The other 46 weeks of the year? Chock-full of episodes from other Slate shows.</p>
</li>
<li>
<p><a href="https://feeds.acast.com/public/shows/software-unscripted">Software Unscripted</a>: I continued to enjoy listening to Richard Feldman’s programming-oriented interview podcast but I’m a little cooler on it than I was last year. I think that’s mostly the fault of the medium: audio isn’t the best format for the deep technical discussions I sometimes want Feldman and his guests to do.</p>
</li>
<li>
<p><a href="https://stratechery.com">The Stratechery Podcast</a> 💰: As mentioned above, I’m a subscriber to Ben Thompson’s Stratechery Plus service and one of the perks is this feed featuring audio versions of his written posts. Thompson has an enviable hit rate for great writing.</p>
</li>
<li>
<p><a href="https://daringfireball.net/thetalkshow/">The Talk Show</a>: Here I am, in 2025, still subscribed to <em>The Talk Show</em> after more than 15 years. I’m not sure what else to say about John Gruber’s podcast about Apple and technology. He’s got to be doing something right.</p>
</li>
</ul>
<h2>Previously Subscribed</h2>
<ul>
<li>
<p><a href="https://audioboom.com/channels/5028672-chinese-whispers"><strong>Chinese Whispers</strong></a>: I’m sad to say that within months of me discovering this excellent podcast in August 2024 about Chinese society and politics from Cindy Yu (formerly of the <em>Spectator</em>), the show had wrapped up. Yu is now at the <em>Times</em> but hasn’t started a show that’s equivalent to <em>Chinese Whispers</em>.</p>
</li>
<li>
<p><a href="https://hiphination.org"><strong>Hi-Phi Nation</strong></a>: Last year I retained a sliver of hope that philosopher Barry Lam might return to his podcast. Alas, it looks like it’s time to admit that’s not going to happen.</p>
</li>
<li>
<p><a href="https://slate.com/podcasts/one-year/"><strong>One Year</strong></a>: This is another podcast that hasn’t officially ended but which hasn’t seen a new episode in long enough that I suspect it’s done. I miss your dulcet tones, Josh Levin!</p>
</li>
<li>
<p><a href="https://podcast.panic.com/"><strong>Panic Podcast</strong></a>: In 2023, I said this show was over. In 2024, it came back. It’s 2025 and it looks like it’s gone once more. What will 2026 bring? Only time will tell!</p>
</li>
<li>
<p><a href="https://sharptech.fm/"><strong>Sharp Tech</strong></a> 💰: While I mostly enjoyed Andrew Sharp and Ben Thompson’s paid podcast about the consumer software industry, I unsubscribed to make way for some of the newer shows I started listening to this year.</p>
</li>
<li>
<p><a href="https://talkeasypod.com"><strong>Talk Easy</strong></a>: Sam Fragoso’s interview show was another victim of me prioritising other podcasts. Fragoso is a terrific interviewer and I recommend it for anyone who is interested in popular culture.</p>
</li>
<li>
<p><a href="https://www.relay.fm/radar"><strong>Under the Radar</strong></a>: Developers Marco Arment and David Smith produce a tight fortnightly discussion of issues in the world of iOS development. I unsubscribed to make way for other shows.</p>
</li>
</ul>
<p>See you next year when this will hopefully be published on time!</p>
<section class="footnotes">
<ol>
<li id="fn1">
<p>Previous years: <a href="https://articles.inqk.net/2024/05/30/podcasts-spring-2024.html" title="Read 'Podcasts I'm Listening To: Spring 2024'">2024</a>, <a href="https://articles.inqk.net/2023/05/29/podcasts-spring-2023.html" title="Read 'Podcasts I'm Listening To: Spring 2023'">2023</a>, <a href="https://articles.inqk.net/2022/05/31/podcasts-spring-2022.html" title="Read 'Podcasts I'm Listening To: Spring 2022'">2022</a>, <a href="https://articles.inqk.net/2021/05/30/podcasts-spring-2021.html" title="Read 'Podcasts I'm Listening To: Spring 2021'">2021</a>, <a href="https://articles.inqk.net/2020/05/31/podcasts-spring-2020.html" title="Read 'Podcasts I'm Listening To: Spring 2020'">2020</a>, <a href="https://articles.inqk.net/2019/05/03/podcasts-spring-2019.html" title="Read 'Podcasts I'm Listening To: Spring 2019'">2019</a> and <a href="https://articles.inqk.net/2018/05/24/podcasts-spring-2018.html" title="Read 'Podcasts I'm Listening To: Spring 2018'">2018</a>. <a href="#fnref1" class="footnote-backref">↩</a></p>
</li>
<li id="fn2">
<p>And then backdating it like a dodgy chief financial officer. <a href="#fnref2" class="footnote-backref">↩</a></p>
</li>
</ol>
</section>

    ]]>
  </content>
</entry>

<entry>
  <title>Recommended Directory Structure for Janet Packages</title>
  <link rel="alternate" type="text/html" href="https://articles.inqk.net/2025/01/09/janet-dir-structure.html" />
	<id>tag:articles.inqk.net,2025-01-09:janet-dir-structure</id>
	<published>2025-01-09T08:56:00+09:00</published>
	<updated>2025-09-18T18:37:09+09:00</updated>
	<author>
		<name>Michael Camilleri</name>
	</author>
	<summary type="text">A recommended directory structure for use by Janet package authors.</summary>
	<content type="html" xml:base="https://articles.inqk.net" xml:lang="en">
    <![CDATA[
    <p><strong><em>For modern bundles, I recommend users follow my <a href="https://articles.inqk.net/2025/09/18/revised-janet-dir-structure.html" title="Read
the article 'Recommended Directory Structure for Janet Bundles'.">revised recommended
directory structure</a>. I leave this post for historical reference.</em></strong></p>
<p>I like making packages for the Janet programming language. I also like things to be neat and consistent. This has led to me spending too much time thinking about a directory structure I can use for my Janet packages.</p>
<p>My suggestion is as follows:</p>
<pre class="code highlight language-txt"><code><span class="line-1">&lt;package&gt;/
</span><span class="line-2">├─ bin/
</span><span class="line-3">├─ deps/
</span><span class="line-4">├─ lib/
</span><span class="line-5">├─ res/
</span><span class="line-6">├─ src/
</span><span class="line-7">├─ test/
</span><span class="line-8">├─ init.janet
</span><span class="line-9">├─ LICENSE
</span><span class="line-10">├─ project.janet
</span><span class="line-11">├─ README.md
</span></code></pre>
<p>To explain:</p>
<ul>
<li><code>bin/</code>: This directory contains the binscripts that your package may provide. In my <a href="https://github.com/pyrmont/lemongrass" title="Visit the GitHub repository for the Lemongrass package.">Lemongrass</a> package, for example, I provide a CLI utility, <code>lg</code>, that is installed together with the package.</li>
</ul>
<ul>
<li>
<p><code>deps/</code>: This directory contains vendored dependencies that your package uses. I’ve moved to using vendored dependencies as a way to avoid some of the issues that arise when you’re trying to share dependencies across all packages.<span class="connector">&#65279;<sup class="footnote-ref"><a href="#fn1" id="fnref1">1</a></sup></span></p>
</li>
<li>
<p><code>lib/</code>: This directory contains the Janet code that is used in your package.</p>
</li>
<li>
<p><code>res/</code>: This directory contains resources (such as fixtures used in testing) that are used by your package.</p>
</li>
<li>
<p><code>src/</code>: This directory contains code (typically C code) that is compiled for use in your package.</p>
</li>
<li>
<p><code>test/</code>: This directory contains tests for your package (the Janet Project Manager includes a built-in task <code>jpm test</code> that will run all Janet files in the <code>test/</code> directory).</p>
</li>
<li>
<p><code>init.janet</code>: This file allows a consumer of your package to import the entire library by simply writing <code>(import &lt;package&gt;</code>) in their Janet file. This is because <code>init.janet</code> is a ‘magic file’ that Janet’s module loader looks for when it tries to resolve an import call. In my <a href="https://github.com/pyrmont/digestive" title="Visit the GitHub repository for the Digestive package.">Digestive</a> package, the MD5 module that is located in <code>lib/md5.janet</code> is exported by <code>init.janet</code> with the <code>md5</code> prefix. This translates to the following usage:</p>
<pre class="code highlight language-janet"><code><span class="line-1"><span class="p">(</span><span class="kr">import</span><span class="w"> </span><span class="n">digestive</span><span class="p">)</span>
</span><span class="line-2">
</span><span class="line-3"><span class="p">(</span><span class="nf">digestive/md5/digest</span><span class="w"> </span><span class="s2">"Hello world"</span><span class="p">)</span>
</span></code></pre>
<p>My documentation tool, <a href="https://github.com/pyrmont/documentarian" title="Visit the GitHub repository for the Documentarian package.">Documentarian</a>, can be used with the <code>-O</code> and <code>-d</code> flags to only document functions that are exported from a file (e.g. <code>init.janet</code>) and remove the prefix (e.g. <code>init/</code>) that would otherwise prefix each binding.</p>
</li>
</ul>
<ul>
<li>
<p><code>project.janet</code>: This file sets up the package for use by JPM, the Janet Project Manager. For libraries written in Janet that follow this directory structure, <code>declare-source</code> should be called with the files to copy on installation of the package together with a prefix (typically the name of the package).</p>
<p>Using Digestive as an example again, this looks like:</p>
<pre class="code highlight language-janet"><code><span class="line-1"><span class="p">(</span><span class="nf">declare-source</span>
</span><span class="line-2"><span class="w">  </span><span class="kc">:source</span><span class="w"> </span><span class="p">[</span><span class="s2">"deps"</span>
</span><span class="line-3"><span class="w">           </span><span class="s2">"lib"</span>
</span><span class="line-4"><span class="w">           </span><span class="s2">"init.janet"</span><span class="p">]</span>
</span><span class="line-5"><span class="w">  </span><span class="kc">:prefix</span><span class="w"> </span><span class="s2">"digestive"</span><span class="p">)</span>
</span></code></pre>
</li>
</ul>
<p>(I’ve left out descriptions for <code>LICENSE</code> and <code>README.md</code> which I assume are self-explanatory.)</p>
<p>I’ve been using this structure for a few months now and have found it works well. I hope it does for you, too!</p>
<section class="footnotes">
<ol>
<li id="fn1">
<p>I’m still working on the best way to install and update vendored dependencies. I have some ideas but nothing I’m certain is the right answer. <a href="#fnref1" class="footnote-backref">↩</a></p>
</li>
</ol>
</section>

    ]]>
  </content>
</entry>

<entry>
  <title>Podcasts I&apos;m Listening To: Spring 2024</title>
  <link rel="alternate" type="text/html" href="https://articles.inqk.net/2024/05/30/podcasts-spring-2024.html" />
	<id>tag:articles.inqk.net,2024-05-30:podcasts-spring-2024</id>
	<published>2024-05-30T12:02:14+09:00</published>
	<updated>2024-05-30T12:47:56+09:00</updated>
	<author>
		<name>Michael Camilleri</name>
	</author>
	<summary type="text">A listing of the podcasts I’m listening to in spring of 2024.</summary>
	<content type="html" xml:base="https://articles.inqk.net" xml:lang="en">
    <![CDATA[
    <p>Seven years in a row! Here’s the latest annual<span class="connector">&#65279;<sup class="footnote-ref"><a href="#fn1" id="fnref1">1</a></sup></span> list of podcasts I’m listening to in spring<span class="connector">&#65279;<sup class="footnote-ref"><a href="#fn2" id="fnref2">2</a></sup></span> of 2024.</p>
<p>As I’ve done in past iterations, the list is broken down into ‘Currently Subscribed’ and ‘Previously Subscribed’<span class="connector">&#65279;<sup class="footnote-ref"><a href="#fn3" id="fnref3">3</a></sup></span> sections. Podcasts that are new to the list are in bold and paid podcasts are marked with a 💰emoji.</p>
<p>Happy listening!</p>
<h2>Currently Subscribed</h2>
<ul>
<li>
<p><a href="https://www.theringer.com/22-goals">22 Goals</a>: After more than a year, I remain deeply in love with Brian Phillips’s history of the World Cup. I still haven’t been able to get anyone to listen to it but love springs eternal so I’m keeping it in the ‘Currently Subscribed’ section regardless of the fact it’s well and truly over.</p>
</li>
<li>
<p><a href="https://atp.fm/">Accidental Tech Podcast</a>: I feel similar to how I did last year: the show has fallen off a bit since the glory years of the late 2010s but it’s still the best Apple tech podcast out there. You don’t have to pay for the show but if you become a member, you get your episodes without ads and with an extra bonus segment.</p>
</li>
<li>
<p><a href="https://atrpodcast.com/">Against the Rules</a>: This, perhaps unsurprisingly, transformed over the past year into something approaching a rolling advertisement for Michael Lewis’ book on Sam Bankman-Fried, <em>Going Infinite</em>. I skipped most of the episodes but have stayed subscribed in the hopes it will return to its classic format in future episodes.</p>
</li>
<li>
<p><a href="https://sscpodcast.libsyn.com/website">Astral Codex Ten Podcast</a>: I love listening to the pseudonymous Solenoid Entity’s cultured Australian accent as he  recites the entries of blogger Scott Alexander.</p>
</li>
<li>
<p><a href="http://timharford.com/articles/cautionarytales/">Cautionary Tales</a>: It felt like a lot of filler in this feed for the past 12 months. I remain of the opinion that economic journalist Tim Harford would be better served by just recording a season’s worth of episodes a year and not updating the feed until the next season. Alas, dear reader, this will be a recurring pattern for Pushkin Industries’ shows.</p>
</li>
<li>
<p><a href="https://corecursive.com">CoRecursive</a>: This is still my favourite programming podcast (although <em>Software Unscripted</em> is an extremely close second). Adam Gordon Bell crafts each episode into a satisfying tale about a piece of software.</p>
</li>
<li>
<p><a href="https://slate.com/podcasts/decoder-ring">Decoder Ring</a>: Willa Paskin records a ‘season’ of five episodes or so about cultural mysteries every few months and releases them on a weekly schedule. It’s great. All the cross-promotion for Slate’s other shows? Not so great.</p>
</li>
<li>
<p><a href="https://dithering.fm/">Dithering</a> 💰: Brevity makes the heart grow fonder? John Gruber and Ben Thompson’s paid podcast consistently makes me wish the episodes were longer.</p>
</li>
<li>
<p><a href="https://greatestofalltalk.com">Greatest of All Talk</a> 💰: I worried last year that my interest in basketball, and hence this show from <em>Washington Post</em> NBA correspondent Ben Golliver and former <em>Sports Illustrated</em> feature writer Andrew Sharp, would wane when the 2023 NBA play-offs wrapped up. Sure enough, that’s what happened but then the 2024 play-offs started and guess who added it back to their podcast player?</p>
</li>
<li>
<p><a href="https://hiphination.org">Hi-Phi Nation</a>: I’m worried I gave the kiss of death to this philosophy show when I celebrated its return last year. It subsequently wrapped season 6 a fortnight before last year’s entry and nary a whisper since then. Come back, Barry Lam!</p>
</li>
<li>
<p><a href="https://slate.com/podcasts/hit-parade">Hit Parade</a>: I’m impressed all over again every time I listen to an episode. Host Chris Molanphy takes the listener on a fascinating journey each month to a different cranny in the history of the U.S. pop music charts. My only wish is for the accompanying playlist for each episode to be made available on Apple Music.</p>
</li>
<li>
<p><a href="https://www.vox.com/land-of-the-giants-podcast"><strong>Land of the Giants</strong></a>: I’m a little reluctant to put this long-form journalistic podcast about tech companies on here because while I did listen to a few of the ‘seasons’ of the show (each season focuses on a different company), I wasn’t that impressed. But you know what I am impressed with? No filler! When the season is finished, they just leave the feed alone. More like this, please!</p>
</li>
<li>
<p><a href="https://www.citationneeded.news/"><strong>Molly White’s Citation Needed</strong></a>: As devoted readers<span class="connector">&#65279;<sup class="footnote-ref"><a href="#fn4" id="fnref4">4</a></sup></span> of this series know, if there’s one thing I love even more than podcasts with seasons, it’s podcasts that involve someone reading blog posts! Blogger Molly White records her newsletter (which is a 2020s way of saying ‘blog’) focusing on AI, cryptocurrency and the world wide web.</p>
</li>
<li>
<p><a href="https://slate.com/podcasts/one-year/">One Year</a>: Josh Levin’s series on contemporary American history (every season is about a different year) hovers very close to the edge of unsubscribe territory for me. I do often enjoy the episodes when I listen to them but when I see an episode in my queue, I frequently want to listen to something else instead. It might not be here next year.</p>
</li>
<li>
<p><a href="https://www.abc.net.au/radionational/programs/partyroom">The Party Room</a>: I can’t believe this show was new to my list last spring; it’s become such an integral part of my week that it feels like I’ve been listening to it for years. ABC journalists, Patricia Karvelas and Fran Kelly, discuss the big political issues in Australian federal politics each week.</p>
</li>
<li>
<p><a href="https://podcast.panic.com/"><strong>Panic Podcast</strong></a>: It was the reverse kiss of death! I pronounced this podcast gone last year but wouldn’t you know it, it looks like they’re coming back with a second season!</p>
</li>
<li>
<p><a href="https://www.therepl.net/">The REPL</a>: This podcast from Clojurist Daniel Compton is pretty close to being cut if I’m being honest. I still love Clojure but it’s a slow-moving ecosystem and there’s not that much to talk about. Fortunately, Compton seems aware of this and so only records episodes sporadically.</p>
</li>
<li>
<p><a href="https://revisionisthistory.com/">Revisionist History</a>: Last year I said that this podcast needs to leave longer gaps between its seasons. It didn’t do that but to his credit, author Malcolm Gladwell did maintain a pretty healthy output of new episodes. As mentioned about other podcasts, I do wish there were a lot fewer cross-promotional episodes.</p>
</li>
<li>
<p><a href="https://serioustrouble.show/">Serious Trouble</a> 💰: Similar to <em>The Party Room</em>, I can’t believe this was new to the list last year. Journalist Josh Barro and lawyer Ken White do an excellent job breaking down the legal troubles affecting those at the centre of American politics.</p>
</li>
<li>
<p><a href="https://sharptech.fm/">Sharp Tech</a> 💰: I mentioned that Andrew Sharp of <em>Greatest of All Talk</em> was a former feature writer for <em>Sports Illustrated</em>. He’s now a professional podcaster and in addition to basketball, discusses technology with Ben Thompson. I do sometimes wish for a better foil for Thompson but Sharp is at least excellent at ‘keeping things moving’ as he likes to say.</p>
</li>
<li>
<p><a href="https://slate.com/podcasts/slow-burn">Slow Burn</a>: The most recently completed season was about Justice Thomas’ journey to the Supreme Court and it was great. Unfortunately, like so many of Slate’s other shows, the <em>Slow Burn</em> producers don’t have the courage to lay low in between seasons and instead stuff the feed with a staggering number of episodes from affiliated shows.</p>
</li>
<li>
<p><a href="https://feeds.acast.com/public/shows/software-unscripted"><strong>Software Unscripted</strong></a>: I’ve long enjoyed watching the conference talks of host Richard Feldman on YouTube. What makes this show work is that Feldman is working on his statically-typed programming language, <a href="https://www.roc-lang.org">Roc</a>, but has a background in front-end web development. This makes him comfortable discussing topics from compilers to web pages. My favourite new podcast.</p>
</li>
<li>
<p><a href="https://stratechery.com">The Stratechery Podcast</a> 💰: Another one of my beloved ‘blogger reads blog posts’ podcasts. Analyst Ben Thompson presents his view on the tech world from a business perspective. I don’t always agree with him but his arguments are always worth considering.</p>
</li>
<li>
<p><a href="https://talkeasypod.com"><strong>Talk Easy</strong></a>：I guess this is why there’s so much cross-promotion. I came across an episode of this in one of the Pushkin Industries’ feeds and liked it enough to try another episode. The main draw for me is how impressive host Sam Fragoso is as an interviewer. He’s extremely well-prepared for his interviews and that causes each subject to speak more freely than you (or often they) expect.</p>
</li>
<li>
<p><a href="https://daringfireball.net/thetalkshow/">The Talk Show</a>: I said last year that there were fewer classic episodes for John Gruber’s long-running Apple-oriented podcast and I still feel the same way. Maybe Merlin Mann will come back.</p>
</li>
<li>
<p><a href="https://www.relay.fm/radar">Under the Radar</a>: iOS developers Marco Arment and David Smith discuss topics relevant to indie development on Apple platforms. It’s never great but it knows not to overstay its welcome.</p>
</li>
</ul>
<h2>Previously Subscribed</h2>
<ul>
<li>
<p><a href="https://www.podpage.com/econ102/"><strong>Econ 102</strong></a>: I really wanted to like this show. Economist Noah Smith discusses an article from his blog with co-host Erik Torenberg. Unfortunately, Torenberg is too ill-informed about the world to make the discussion interesting.</p>
</li>
<li>
<p><a href="https://coldtakesblog.podbean.com/"><strong>Cold Takes Audio</strong></a>: I said last year that Holden Karnofsky was doing what I wanted other bloggers to do and then he promptly stopped blogging (or at least has effectively stopped blogging).</p>
</li>
<li>
<p><a href="https://exponent.fm/"><strong>Exponent</strong></a>: I’ve kept this on the Currently Subscribed list for a while but it’s time to admit it’s gone. Farewell, James! May you long avoid barbed-wire fences!</p>
</li>
<li>
<p><a href="https://twitter.com/musicalsplainin"><strong>MusicalSplaining</strong></a>: I stopped listening to this and then, just when I was feeling guilty, hosts Angela Meehan and Kaveh Taherian announced the show was ending. I’ll always have fond memories.</p>
</li>
<li>
<p><a href="https://www.abc.net.au/radionational/programs/philosopherszone/"><strong>Philosopher’s Zone</strong></a>: I think I need to admit that I’ve stopped listening to this podcast. I’m technically still subscribed but I have a huge backlog of episodes that I periodically go through and delete rather than listen to. David Rutledge did a great job making philosophy accessible to the layperson and my dropping it reflects more on me than it does on the show.</p>
</li>
<li>
<p><a href="https://www.theringer.com/the-rewatchables"><strong>The Rewatchables</strong></a>: Like the <em>Philosopher’s Zone</em>, I have a lot of fond memories but the reality is that I only have so many hours in the day and in the end, I’d rather spend that time watching movies than listening to Bill Simmons and friends talk about them.</p>
</li>
<li>
<p><a href="https://www.slowboring.com/"><strong>Slow Boring</strong></a>: I was hopeful that Matt Yglesias would get someone to read his blog posts but that’s not the direction he’s gone. He sporadically has interviews but I don’t find them especially good; interviewing people isn’t Yglesias’ strength.</p>
</li>
</ul>
<p>I can’t believe I’ve been writing these for the better part of a decade but I guess it’d be a waste to stop before I get to 10 so see you all again next year!</p>
<section class="footnotes">
<ol>
<li id="fn1">
<p>Previous years: <a href="https://articles.inqk.net/2023/05/29/podcasts-spring-2023.html" title="Read 'Podcasts I'm Listening To: Spring 2023'">2023</a>, <a href="https://articles.inqk.net/2022/05/31/podcasts-spring-2022.html" title="Read 'Podcasts I'm Listening To: Spring 2022'">2022</a>, <a href="https://articles.inqk.net/2021/05/30/podcasts-spring-2021.html" title="Read 'Podcasts I'm Listening To: Spring 2021'">2021</a>, <a href="https://articles.inqk.net/2020/05/31/podcasts-spring-2020.html" title="Read 'Podcasts I'm Listening To: Spring 2020'">2020</a>, <a href="https://articles.inqk.net/2019/05/03/podcasts-spring-2019.html" title="Read 'Podcasts I'm Listening To: Spring 2019'">2019</a> and <a href="https://articles.inqk.net/2018/05/24/podcasts-spring-2018.html" title="Read 'Podcasts I'm Listening To: Spring 2018'">2018</a>. <a href="#fnref1" class="footnote-backref">↩</a></p>
</li>
<li id="fn2">
<p>Technically. <a href="#fnref2" class="footnote-backref">↩</a></p>
</li>
<li id="fn3">
<p>Extremely alert readers may notice that the ‘Previously Subscribed’ includes podcasts that weren’t in last year’s list. This is the dirty little secret of these lists: they’re really about what I listened to in the previous 12 months. <a href="#fnref3" class="footnote-backref">↩</a></p>
</li>
<li id="fn4">
<p>It’s just me, isn’t it? <a href="#fnref4" class="footnote-backref">↩</a></p>
</li>
</ol>
</section>

    ]]>
  </content>
</entry>

<entry>
  <title>How-To: Installing Void Linux on a Raspberry Pi</title>
  <link rel="alternate" type="text/html" href="https://articles.inqk.net/2023/07/12/how-to-install-void.html" />
	<id>tag:articles.inqk.net,2023-07-12:how-to-install-void</id>
	<published>2023-07-12T14:58:02+09:00</published>
	<updated>2024-01-13T08:30:45+09:00</updated>
	<author>
		<name>Michael Camilleri</name>
	</author>
	<summary type="text">Instructions on how to install Void Linux on a Raspberry Pi 3 Model B.</summary>
	<content type="html" xml:base="https://articles.inqk.net" xml:lang="en">
    <![CDATA[
    <p>This is a short tutorial for how to install Void Linux on a Raspberry Pi 3 Model B.</p>
<h2>Pre-Requisites</h2>
<p>I used the following:</p>
<ol>
<li>Raspberry Pi 3 Model B</li>
<li>16GB microSD card</li>
<li>Monitor</li>
<li>Keyboard</li>
</ol>
<p>Regarding the third and fourth items, we do want to get the Pi ready for SSH access as soon as possible but at the very beginning it’s great to have direct access to the machine.</p>
<p>If you have a different model of Raspberry Pi, these instructions might still work but bear in mind that your mileage may vary.</p>
<h2>Steps</h2>
<h3>Step 1. Download a live image</h3>
<p>Void Linux makes <a href="https://voidlinux.org/download/" title="Download the Void Linux live images for Raspberry Pi devices">live images</a> available for Raspberry Pi devices. I downloaded the glibc version of the rpi-armv7l live image because I’m afraid of trying new things but if you live life on the edge try the musl version and let me know if the rest of this guide worked for you!</p>
<h3>Step 2. Install the live image</h3>
<p>Use whatever tool you prefer to install the live image onto your SD card. I went with <a href="https://etcher.balena.io" title="The home page for Balena Etcher">Etcher</a>.</p>
<h3>Step 3. Boot the Raspberry Pi</h3>
<p>Install the SD card into your Pi and start it up. If all goes well, you should find yourself at a login prompt. At the time of writing, the live image has a <code>root</code> user with password <code>voidlinux</code>.</p>
<h3>Step 4. Resize root partition</h3>
<p>The live image contains two partitions: a boot partition and the root partition. The bad news is that the root partition is only 2GB. The good news is that we can resize it from within Void.<span class="connector">&#65279;<sup class="footnote-ref"><a href="#fn1" id="fnref1">1</a></sup></span> Normally, it’s not advisable to resize a partition while you’re using it, but since the root partition comes at the ‘end’ of the partition table, we can safely extend it into the remaining space without any issues.</p>
<p>We’ll resize with sfdisk so let’s start it up. We need to pass <code>--force</code> so that we can change a partition that’s in use:</p>
<pre class="code highlight language-console"><code><span class="line-1"><span class="gp">#</span><span class="w"> </span>sfdisk <span class="nt">-N</span> 2 /dev/mmcblk0 <span class="nt">--force</span>
</span></code></pre>
<p>sfdisk will greet you with a scary warning. Fear not; we don’t have much to do. Next input the following in the sfdisk shell:</p>
<pre class="code highlight language-console"><code><span class="line-1"><span class="go">/dev/mmcblk0p2: - +</span>
</span></code></pre>
<p>Is that it? What does it mean? Well, the <code>-</code> tells sfdisk to leave the beginning of the partition where it is and the <code>+</code> tells it to fill the remaining space. After the command is received, sfdisk will show you the new partition table and ask if you want to write this to disk. Press <code>y</code> to confirm.</p>
<p>Reboot your system:</p>
<pre class="code highlight language-console"><code><span class="line-1"><span class="gp">#</span><span class="w"> </span>reboot now
</span></code></pre>
<p>Log back in and resize the file system:</p>
<pre class="code highlight language-console"><code><span class="line-1"><span class="gp">#</span><span class="w"> </span>resize2fs /dev/mmcblk0p2
</span></code></pre>
<p>Restart, log in and confirm the changes are reflected in the partition table:</p>
<pre class="code highlight language-console"><code><span class="line-1"><span class="gp">#</span><span class="w"> </span><span class="nb">df</span> <span class="nt">-h</span>
</span></code></pre>
<p>You should see <code>/dev/root</code> is now almost the full size of the SD card.</p>
<h3>Step 5. Get on Wi-Fi</h3>
<p>Three points to note up front:</p>
<ul>
<li>The next couple of steps draw heavily on Kevin Patel’s <a href="https://blog.kevindirect.com/post/20191109_nine-steps-to-void-linux-on-rpi/" title="Read 'Nine Steps to Void Linux on Raspberry Pi'">excellent guide</a>. Thank you Kevin for writing this. I don’t think I would have got my setup working without it!</li>
</ul>
<ul>
<li>
<p>The default shell for the root user is Dash. It does not have the same niceties as Bash (particularly tab completion) and so while I’ve omitted the invocations to focus on the key aspects, I strongly recommend running <code>bash</code> after every reboot.</p>
</li>
<li>
<p>If you’re not using Wi-Fi, feel free to skip this step.</p>
</li>
</ul>
<p>We need to find out the name of our wireless device. It’s probably something like <code>wlan0</code> but for the rest of this post, I’ll refer to it as <code>&lt;device&gt;</code>.</p>
<p>Find the name:</p>
<pre class="code highlight language-console"><code><span class="line-1"><span class="gp">#</span><span class="w"> </span>ip <span class="nb">link</span>
</span></code></pre>
<p>Change to the following directory:</p>
<pre class="code highlight language-console"><code><span class="line-1"><span class="gp">#</span><span class="w"> </span><span class="nb">cd</span> /etc/wpa_supplicant
</span></code></pre>
<p>Make a copy of the default configuration:</p>
<pre class="code highlight language-console"><code><span class="line-1"><span class="gp">#</span><span class="w"> </span><span class="nb">cp </span>wpa_supplicant.conf wpa_supplicant-&lt;device&gt;.conf
</span></code></pre>
<p>Add the network details:</p>
<pre class="code highlight language-console"><code><span class="line-1"><span class="gp">#</span><span class="w"> </span>wpa_passphrase &lt;ssid&gt; &lt;key&gt; <span class="o">&gt;&gt;</span> wpa_supplicant-&lt;device&gt;.conf
</span></code></pre>
<p>Start the daemon:</p>
<pre class="code highlight language-console"><code><span class="line-1"><span class="gp">#</span><span class="w"> </span>wpa_supplicant <span class="nt">-B</span> <span class="nt">-i</span>&lt;device&gt; <span class="nt">-cwpa_supplicant-</span>&lt;device&gt;.conf
</span></code></pre>
<p>Enable the dhcpd service:<span class="connector">&#65279;<sup class="footnote-ref"><a href="#fn2" id="fnref2">2</a></sup></span></p>
<pre class="code highlight language-console"><code><span class="line-1"><span class="gp">#</span><span class="w"> </span><span class="nb">ln</span> <span class="nt">-s</span> /etc/sv/dhcpcd /var/service/
</span></code></pre>
<p>Test the connection:</p>
<pre class="code highlight language-console"><code><span class="line-1"><span class="gp">#</span><span class="w"> </span>ping voidlinux.org
</span></code></pre>
<p>Hopefully you’re seeing sweet responses. Enable the wpa_supplicant service:</p>
<pre class="code highlight language-console"><code><span class="line-1"><span class="gp">#</span><span class="w"> </span><span class="nb">ln</span> <span class="nt">-s</span> /etc/sv/wpa_supplicant /var/service/
</span></code></pre>
<h3>Step 6. Set up the system time</h3>
<p>Unlike most computers, the Raspberry Pi does not have a battery-powered clock that it uses to ‘remember’ the current time when you shut it down. This can cause issues when updating packages so now that we have access to the Internet, let’s enable the system time daemon:</p>
<pre class="code highlight language-console"><code><span class="line-1"><span class="gp">#</span><span class="w"> </span><span class="nb">ln</span> <span class="nt">-s</span> /etc/sv/ntpd /var/service/
</span></code></pre>
<p>Reconfigure chrony:</p>
<pre class="code highlight language-console"><code><span class="line-1"><span class="gp">#</span><span class="w"> </span>xbps-reconfigure <span class="nt">-f</span> chrony
</span></code></pre>
<p>Reboot again, log in and check if it works (you might need to wait a little for chrony to contact the server and update):</p>
<pre class="code highlight language-console"><code><span class="line-1"><span class="gp">#</span><span class="w"> </span><span class="nb">date</span>
</span></code></pre>
<h3>Step 7. Sync and update</h3>
<p>Sync and update:</p>
<pre class="code highlight language-console"><code><span class="line-1"><span class="gp">#</span><span class="w"> </span>xbps-install <span class="nt">-Su</span>
</span></code></pre>
<p>Run this again to make sure everything is up to date:</p>
<pre class="code highlight language-console"><code><span class="line-1"><span class="gp">#</span><span class="w"> </span>xbps-install <span class="nt">-Su</span>
</span></code></pre>
<h3>Step 8. Set up D-Bus</h3>
<p>Enable the dbus daemon:</p>
<pre class="code highlight language-console"><code><span class="line-1"><span class="gp">#</span><span class="w"> </span><span class="nb">ln</span> <span class="nt">-s</span> /etc/sv/dbus /var/service/
</span></code></pre>
<p>Reboot:</p>
<pre class="code highlight language-console"><code><span class="line-1"><span class="gp">#</span><span class="w"> </span>reboot now
</span></code></pre>
<h3>Step 9. Set up SSH</h3>
<p>Enable the sshd daemon:</p>
<pre class="code highlight language-console"><code><span class="line-1"><span class="gp">#</span><span class="w"> </span><span class="nb">ln</span> <span class="nt">-s</span> /etc/sv/sshd /var/service/
</span></code></pre>
<p>Find your IP address:</p>
<pre class="code highlight language-console"><code><span class="line-1"><span class="gp">#</span><span class="w"> </span>ip addr
</span></code></pre>
<p>Try to SSH from another machine:</p>
<pre class="code highlight language-console"><code><span class="line-1"><span class="gp">#</span><span class="w"> </span>ssh root@&lt;ip-address&gt;
</span></code></pre>
<h3>Step 10. Create an ordinary user</h3>
<p>Create a user and add it to some basic groups:<span class="connector">&#65279;<sup class="footnote-ref"><a href="#fn3" id="fnref3">3</a></sup></span></p>
<pre class="code highlight language-console"><code><span class="line-1"><span class="gp">#</span><span class="w"> </span>useradd <span class="nt">-m</span> <span class="nt">-s</span> /bin/bash <span class="nt">-g</span> <span class="nb">users</span> <span class="nt">-G</span> wheel,network,audio,video &lt;username&gt;
</span></code></pre>
<p>Change the password:</p>
<pre class="code highlight language-console"><code><span class="line-1"><span class="gp">#</span><span class="w"> </span>passwd &lt;username&gt;
</span></code></pre>
<p>To give users in the wheel group the power to <code>sudo</code>, first start <code>visudo</code>:</p>
<pre class="code highlight language-console"><code><span class="line-1"><span class="gp">#</span><span class="w"> </span>visudo
</span></code></pre>
<p>Then uncomment the following:</p>
<pre class="code highlight language-conf"><code><span class="line-1"><span class="c"># %wheel ALL=(ALL) ALL</span>
</span></code></pre>
<p>At this point, you should be able to SSH into the Pi as your new user.</p>
<h2>Wrap-Up</h2>
<p>At this point, you probably want to tweak your SSH configuration (<code>/etc/ssh/sshd_config</code>) but I’ll leave that, and any other software you want to install up to you. Welcome to the Void!</p>
<section class="footnotes">
<ol>
<li id="fn1">
<p>If you create your own image from the rootfs tarballs, you can choose a different size. I found this process intimidating and went with the simpler approach of resizing the root partition. <a href="#fnref1" class="footnote-backref">↩</a></p>
</li>
<li id="fn2">
<p>One of the differences between Void Linux and most other Linux distributions is that it does not use systemd. The runit system that Void uses instead loads the entries that are in <code>/var/service</code>. The common practice is to symlink services you want to ‘enable’ into this directory. <a href="#fnref2" class="footnote-backref">↩</a></p>
</li>
<li id="fn3">
<p>Perhaps betraying its BSD heritage, Void Linux calls its admin group ‘wheel’ by default. <a href="#fnref3" class="footnote-backref">↩</a></p>
</li>
</ol>
</section>

    ]]>
  </content>
</entry>

<entry>
  <title>Podcasts I&apos;m Listening To: Spring 2023</title>
  <link rel="alternate" type="text/html" href="https://articles.inqk.net/2023/05/29/podcasts-spring-2023.html" />
	<id>tag:articles.inqk.net,2023-05-29:podcasts-spring-2023</id>
	<published>2023-05-29T13:26:14+09:00</published>
	<updated>2023-05-29T13:44:07+09:00</updated>
	<author>
		<name>Michael Camilleri</name>
	</author>
	<summary type="text">A listing of the podcasts I’m listening to in spring of 2023.</summary>
	<content type="html" xml:base="https://articles.inqk.net" xml:lang="en">
    <![CDATA[
    <p>I’m squeaking in again with the sixth annual<span class="connector">&#65279;<sup class="footnote-ref"><a href="#fn1" id="fnref1">1</a></sup></span> list of podcasts I’m listening to in spring of 2023.</p>
<p>As I’ve done in past iterations, the list is broken down into ‘Currently Subscribed’ and ‘Previously Subscribed’<span class="connector">&#65279;<sup class="footnote-ref"><a href="#fn2" id="fnref2">2</a></sup></span> sections. Podcasts that are new to the list are in bold and paid podcasts are marked with a 💰emoji.</p>
<p>Happy listening!</p>
<h2>Currently Subscribed</h2>
<ul>
<li>
<p><a href="https://www.theringer.com/22-goals"><strong>22 Goals</strong></a>: I love Brian Phillips’s hilarious, freewheeling, inventive and poignant exploration of the history of the World Cup. I’ve never tried so hard to get friends to watch or listen to a piece of media (none of whom did so as best as I can tell). I love the series so much I’m putting it in the ‘Currently Subscribed’ section even though it’s almost certain there will be no more episodes.</p>
</li>
<li>
<p><a href="https://atp.fm/">Accidental Tech Podcast</a>: I’m still a devout listener of the pre-eminent Apple tech podcast (and a very happy paying member) but I have felt the show has lost a tiny amount of its verve now that Apple has largely fixed all of the Mac hardware problems of the late-2010s. Perhaps the rumoured upcoming headset will provide more grist for the mill.</p>
</li>
<li>
<p><a href="https://atrpodcast.com/">Against the Rules</a>: This podcast by author Michael Lewis (of <em>Moneyball</em>, the <em>Big Short</em> fame) was pretty quiet over the past year as he worked on a book about Sam Bankman-Fried. While the fourth season still hasn’t been released, Lewis has started releasing recordings of research interviews he’s conducted in connection with the aforementioned book and these are tiding me over.</p>
</li>
<li>
<p><a href="https://sscpodcast.libsyn.com/website">Astral Codex Ten Podcast</a>: More than a year in and I remain grateful that the pseudonymous Solenoid Entity puts in so much time to reading blogger Scott Alexander’s prolix posts and disappointed so few bloggers have replicated this approach. Perhaps generative A.I. can help?</p>
</li>
<li>
<p><a href="http://timharford.com/articles/cautionarytales/">Cautionary Tales</a>: I really like the idea of podcasts having ‘seasons’ and while pop economist Tim Harford’s does, its in name only. Harford puts out a show practically weekly rather than giving you time to miss him. That’s a real shame because last year’s ‘The South Pole Race’ and ‘The Inventor Who Almost Ended the World’ deserve to land with a more forceful impact than I fear they did.</p>
</li>
<li>
<p><a href="https://coldtakesblog.podbean.com/"><strong>Cold Takes Audio</strong></a>: Holden Karnofsky does what I’m begging more bloggers to do and reads his posts about A.I. and the problems of the modern world. The name is a play on ‘hot takes’. Karnofsky writes his entries a month or more before he publishes them and tries to avoid being overly reactionary.</p>
</li>
<li>
<p><a href="https://corecursive.com">CoRecursive</a>: I wrote last year that my Currently Subscribed list had a lot of programming interview shows. Famous last words because there are now just two. Adam Gordon Bell’s made the cut.</p>
</li>
<li>
<p><a href="https://slate.com/podcasts/decoder-ring">Decoder Ring</a>: Host Willa Paskin’s masterful podcast about pop culture mysteries continues to churn out fantastic episodes. This is easily the podcast I bring up the most in conversation with my wife.</p>
</li>
<li>
<p><a href="https://dithering.fm/">Dithering</a> 💰: John Gruber and Ben Thompson’s paid podcast remains appointment listening for me. I mentioned above that ATP had lost some of its verve; not so <em>Dithering</em>.</p>
</li>
<li>
<p><a href="https://exponent.fm/">Exponent</a>: I worried last year if James Allworth and Ben Thompson would ever release another episode. Then, like an early Christmas present, die-hards were rewarded with an episode about ChatGPT in early December. Nothing since and I suspect we’ll be lucky to get more than one in the next 12 months.</p>
</li>
<li>
<p><a href="https://greatestofalltalk.com"><strong>Greatest of All Talk</strong></a> 💰: I was a regular listener to <em>Open Floor</em>, the NBA podcast from <em>Sports Illustrated</em> that first paired Ben Golliver and Andrew Sharp. I even followed Golliver and Sharp behind the paywall of this show at first. But once the pandemic struck in 2020 and the NBA temporarily stopped, I found it impossible to justify and dropped it. That was until its inclusion in the <a href="https://stratechery.com/stratechery-plus/">Stratechery Plus</a> bundle. Golliver and Sharp are still great; I do worry if my interest in basketball will wane again once we hit the off-season.</p>
</li>
<li>
<p><a href="https://hiphination.org">Hi-Phi Nation</a>: It took me a long time to start listening to Barry Lam’s philosophy podcast but I’m glad that I eventually got there. The wait between season 5 and season 6 was long but I’m excited that Lam is back (pay attention Gladwell and Harford!).</p>
</li>
<li>
<p><a href="https://slate.com/podcasts/hit-parade">Hit Parade</a>: This is such a well-produced show. Chris Molanphy reads a meticulously researched essay each month on some aspect related to the U.S. pop music charts. Each episode is peppered with precisely the right number of samples (a playlist of which is alas only made available on Spotify).</p>
</li>
<li>
<p><a href="https://twitter.com/musicalsplainin">MusicalSplaining</a>: I have wondered more than once if I should keep subscribing to this show reviewing musicals given that I am not especially interested in musicals. Hosts Angela Meehan and Kaveh Taherian make me laugh just enough to keep me subscribed.</p>
</li>
<li>
<p><a href="https://slate.com/podcasts/one-year/">One Year</a>: I listen mainly because I love host Josh Levin’s voice. Each season, he retells stories from a single year in American history.</p>
</li>
<li>
<p><a href="https://www.abc.net.au/radionational/programs/partyroom"><strong>The Party Room</strong></a>: I’d fallen out of touch with Australian politics until a friend recommended this show from Radio National mainstays Patricia Karvelas and Fran Kelly. Just the right length and its gimmick of a special guest each week ensures it avoids becoming stale and repetitive.</p>
</li>
<li>
<p><a href="https://www.abc.net.au/radionational/programs/philosopherszone/">Philosopher’s Zone</a>: I leave this one off my primary playlist and then catch up on the episodes when the mood strikes. Host David Rutledge keeps on having interesting, in-depth conversations with academic experts about philosophical ideas.</p>
</li>
<li>
<p><a href="https://www.therepl.net/">The REPL</a>: I cut a lot of programming podcasts out of the rotation this year and if I had to explain why this Clojure-related interview show avoided that fate, I’d have to admit that it’s almost entirely due to host Daniel Compton’s New Zealand accent.</p>
</li>
<li>
<p><a href="https://revisionisthistory.com/">Revisionist History</a>: Like <em>Cautionary Tales</em>, this podcast needs to leave longer gaps between its seasons (and not stuff its feed with so many ‘special episodes’ cross-promoting other Pushkin shows). That quibble aside, I still enjoy Malcolm Gladwell’s brand of ‘well, actually’ explorations. If you like Gladwell, you’ll like this.</p>
</li>
<li>
<p><a href="https://www.theringer.com/the-rewatchables">The Rewatchables</a>: This past year, I continued my strategy of only listening to episodes for films that take my fancy and it’s worked great. If you listen to any other movie discussion show, you’ll realise how talented Bill Simmons and crew are at this.</p>
</li>
<li>
<p><a href="https://serioustrouble.show/"><strong>Serious Trouble</strong></a> 💰: I was a huge fan of Josh Barro and Ken White’s previous show, <em>All the President’s Lawyers</em>. That one focused on the U.S. President but this show doesn’t restrict itself with so narrow a scope and is all the better for it. Barro and White have terrific chemistry which makes the annual subscription a no-brainer.</p>
</li>
<li>
<p><a href="https://sharptech.fm/"><strong>Sharp Tech</strong></a> 💰: While the combination of superstar tech analyst Ben Thompson and ex-sportswriter Andrew Sharp doesn’t sound like it’d make a great tech show, the secret is that Sharp is also an ex-attorney (!) who is both happy to play second fiddle to Thompson and confident enough to push back against Thompson’s laissez-faire instincts. Another regular listen that comes as part of Stratechery Plus.</p>
</li>
<li>
<p><a href="https://www.slowboring.com/">Slow Boring</a>: I desperately want Matt Yglesias (or someone he pays) to read his blog posts and stay subscribed to this feed in the apparently vain hope that will one day happen. Podcast platform Curio was doing it for a time but they’ve stopped.</p>
</li>
<li>
<p><a href="https://slate.com/podcasts/slow-burn">Slow Burn</a>: Season 7 was an extremely timely look at <em>Roe v Wade</em> and showcased what this show does so well: put an extremely well-known event into the appropriate historical context. I’m looking forward to season 8.</p>
</li>
<li>
<p><a href="https://stratechery.com">The Stratechery Podcast</a> 💰: The initial plank around which Ben Thompson has been slowly building his budding podcast empire at <a href="https://stratechery.com/stratechery-plus/">Stratechery Plus</a>. The premise is simple: Thompson reads his blog posts.</p>
</li>
<li>
<p><a href="https://daringfireball.net/thetalkshow/">The Talk Show</a>: I’m still subscribed to John Gruber’s long-running podcast about Apple but I do feel like there are fewer classic episodes than there used to be.</p>
</li>
<li>
<p><a href="https://www.relay.fm/radar"><strong>Under the Radar</strong></a>: I dropped this in 2020 but picked it back up again (perhaps subconsciously dismayed at the number of programming-related podcasts I cut out of my rotation this year). Marco Arment and David Smith spend about 30 minutes every two weeks talking about the issues they’re facing as developers on Apple platforms.</p>
</li>
</ul>
<h2>Previously Subscribed</h2>
<ul>
<li>
<p><a href="https://mailchimp.com/presents/podcast/sonic-symbolism/"><strong>Björk: Sonic Symbolism</strong></a>: Björk dominated my listening in the late 90s and early 2000s and her albums from <em>Debut</em> to <em>Vespertine</em> remain some of my favourites. I thought I was exactly the target audience for her miniseries about her discography. Instead, I bailed after the first episode.</p>
</li>
<li>
<p><a href="https://www.theringer.com/book-of-basketball"><strong>The Book of Basketball 2.0</strong></a>: As is true of a couple of other podcasts in this section, I’m still technically subscribed but there have been no new episodes in a year and I’m not confident there will be.</p>
</li>
<li>
<p><a href="https://clojure.stream"><strong>ClojureStream Podcast</strong></a>: I wrote last year that this was a bit of a hit and miss show and in the end it had too many misses.</p>
</li>
<li>
<p><a href="https://hollinger-duncan.simplecast.com"><strong>Hollinger &amp; Duncan</strong></a>: I keep going back and forth between subscribing and unsubscribing to the free feed of this NBA podcast from hosts John Hollinger and Nate Duncan. As of this writing I’m unsubscribed in Overcast but I keep an eye on its feed and do grab the occasional episode.</p>
</li>
<li>
<p><a href="https://www.bbc.co.uk/programmes/p02nrss1"><strong>More Or Less</strong></a>: This felt like a more pertinent listen during the height of the pandemic. Since then, I’ve found myself far less interested.</p>
</li>
<li>
<p><a href="https://craigmod.com/onmargins/"><strong>On Margins</strong></a>: I’m pronouncing this one dead. I’ll keep subscribed for another chance to listen to Craig Mod’s whispering voice but I’m not hopeful.</p>
</li>
<li>
<p><a href="https://podcast.panic.com/"><strong>Panic Podcast</strong></a>: Another podcast I’m confident has carked it. Sometimes it’s good to know when you’re finished.</p>
</li>
<li>
<p><a href="https://popculturedetective.agency"><strong>Pop Culture Detective: Audio Files</strong></a>: I enjoy the thoughtfulness that Jonathan McIntosh brings to his analysis but with three kids under 10, I’m too time poor to keep up with the media he’s discussing.</p>
</li>
<li>
<p><a href="https://sharpchina.fm/"><strong>Sharp China</strong></a> 💰: I’ve listened to this show since it debuted as part of Stratechery Plus but cut it the week I’m writing this. While the rise of China is one of the most important geopolitical developments in my lifetime (and I want to understand it better), a truly great exploration of the impact of this needs to feature specific subject matter experts rather than a generalist like Bill Bishop.</p>
</li>
<li>
<p><a href="https://www.softwaresessions.com/"><strong>Software Sessions</strong></a>: I did indeed curse this show by proclaiming it my favourite programming interview show of 2021.</p>
</li>
<li>
<p><a href="https://www.swiftbysundell.com"><strong>Swift by Sundell</strong></a>: John Sundell’s interview show with people in the iOS community was another casualty of the complete lack of time I’ve had in the past year to do almost any programming work.</p>
</li>
<li>
<p><a href="https://www.hackingwithswift.com/interviews/"><strong>Swiftly Speaking</strong></a>: Still no new episodes since last year’s post. Put this show down as one I’m cutting because it died.</p>
</li>
<li>
<p><a href="https://www.patreon.com/ThinkingBasketball"><strong>Thinking Basketball</strong></a>: Ben Taylor of the Thinking Basketball YouTube channel has a podcast of the same name. I couldn’t justify the time it was taking up but I have very pleasant memories of spending late summer and early autumn listening to the 10-episode series on the top 40 NBA careers of all time.</p>
</li>
<li>
<p><a href="https://slate.com/podcasts/thrilling-tales-of-modern-capitalism"><strong>Thrilling Tales of Modern Capitalism</strong></a>: This was the Slate infotainment podcast I loved before all the others. I’m not sure what happened but there’ve been no new episodes since July 2021 so I’m declaring it over.</p>
</li>
</ul>
<p>Are you surprised I’m still doing this? Let’s see if I’m back again next year!</p>
<section class="footnotes">
<ol>
<li id="fn1">
<p>Previous years: <a href="https://articles.inqk.net/2022/05/31/podcasts-spring-2022.html" title="Read 'Podcasts I'm Listening To: Spring 2022'">2022</a>, <a href="https://articles.inqk.net/2021/05/30/podcasts-spring-2021.html" title="Read 'Podcasts I'm Listening To: Spring 2021'">2021</a>, <a href="https://articles.inqk.net/2020/05/31/podcasts-spring-2020.html" title="Read 'Podcasts I'm Listening To: Spring 2020'">2020</a>, <a href="https://articles.inqk.net/2019/05/03/podcasts-spring-2019.html" title="Read 'Podcasts I'm Listening To: Spring 2019'">2019</a> and <a href="https://articles.inqk.net/2018/05/24/podcasts-spring-2018.html" title="Read 'Podcasts I'm Listening To: Spring 2018'">2018</a>. <a href="#fnref1" class="footnote-backref">↩</a></p>
</li>
<li id="fn2">
<p>Extremely alert readers may notice that the ‘Previously Subscribed’ includes podcasts that weren’t in last year’s list. This is the dirty little secret of these lists: they’re really about what I listened to in the previous 12 months. <a href="#fnref2" class="footnote-backref">↩</a></p>
</li>
</ol>
</section>

    ]]>
  </content>
</entry>

<entry>
  <title>Role-Playing with ChatGPT: Sell the Charlotte Hornets</title>
  <link rel="alternate" type="text/html" href="https://articles.inqk.net/2023/04/10/air-gpt.html" />
	<id>tag:articles.inqk.net,2023-04-10:air-gpt</id>
	<published>2023-04-10T06:19:57+09:00</published>
	<updated>2023-04-10T06:38:16+09:00</updated>
	<author>
		<name>Michael Camilleri</name>
	</author>
	<summary type="text">I role play as Michael Jordan's wife trying to convince him to sell the Charlotte Hornets NBA franchise.</summary>
	<content type="html" xml:base="https://articles.inqk.net" xml:lang="en">
    <![CDATA[
    <p><em><strong>Me</strong>: Can you pretend to be Michael Jordan talking to his wife? I’m going to role play as Michael Jordan’s wife.</em></p>
<p><strong>ChatGPT</strong>: Sure, I can respond accordingly. Go ahead!</p>
<p><em><strong>Me</strong>: Babe, Gordon Hayward was the worst signing you’ve ever done. You need to cut him.</em></p>
<p><strong>ChatGPT</strong>: As Michael Jordan, I understand that you have concerns about the team’s performance and the impact of certain players, such as Gordon Hayward. While I appreciate your feedback and perspective, as the owner of the Charlotte Hornets, I need to consider a variety of factors when making personnel decisions, including contractual obligations and the long-term vision for the team.</p>
<p>That being said, I value your input and will certainly take your concerns into consideration as we continue to evaluate our roster and make decisions moving forward. Thank you for being such an important part of my life and supporting me in my role with the team.</p>
<p><em><strong>Me</strong>: I’m your wife. Be honest. He’s been awful, right?</em></p>
<p><strong>ChatGPT</strong>: As Michael Jordan, I understand your concern about Gordon Hayward’s performance. While he has certainly faced some challenges this season, I believe that he is a talented player who has the potential to contribute to our team’s success.</p>
<p>As the owner of the team, I also need to consider the broader context of our performance and the long-term goals we have for the organization. This includes factors like salary cap implications, our overall team strategy, and the development of younger players on our roster.</p>
<p>Ultimately, I believe that we have a talented group of players who are capable of achieving success if we work together and continue to focus on improvement. While we may face some bumps in the road along the way, I am confident that we can overcome any obstacles and achieve our goals as a team.</p>
<p><em><strong>Me</strong>: Babe, I can’t believe you’re taking to me like this. I’m your wife not ESPN. Sound like a human being.</em></p>
<p><strong>ChatGPT</strong>: I apologize if my previous response sounded too formal. As your husband and not just the owner of the Charlotte Hornets, I value your opinion and want to be honest with you.</p>
<p>Regarding Gordon Hayward’s performance, I agree that it has been disappointing so far this season. We had high hopes for him, and I know that many fans and supporters of the team have been frustrated with his lack of production.</p>
<p>That being said, we also need to remember that basketball is a team sport, and it’s not always fair to place all the blame or praise on one player. Our entire team needs to work together and step up if we want to achieve success.</p>
<p>I appreciate your support and your willingness to speak candidly with me about your concerns. Let’s continue to work together and support each other as we navigate the challenges and opportunities ahead.</p>
<p><em><strong>Me</strong>: You know I’m always honest with you, right?</em></p>
<p><strong>ChatGPT</strong>: Yes, I know that you are always honest with me. That’s one of the things I love and appreciate about you. Your honesty and candor help me make better decisions both in my personal life and as the owner of the Charlotte Hornets. Thank you for always being there for me and supporting me in everything I do.</p>
<p><em><strong>Me</strong>: Babe, you’re a terrible owner.</em></p>
<p><strong>ChatGPT</strong>: I understand that you may have some frustrations with the performance of the team, and I am sorry if my decisions as the owner have contributed to those frustrations. However, I believe that as an owner, I have a responsibility to make difficult decisions that are in the best interests of the team both in the short and long term.</p>
<p>I am always open to feedback and constructive criticism, and I welcome any suggestions or ideas you may have for how we can improve the team’s performance. Let’s continue to work together to support the Charlotte Hornets and help them achieve success on and off the court.</p>
<p><em><strong>Me</strong>: It’s hopeless, Mike. You need to sell the team.</em></p>
<p><strong>ChatGPT</strong>: I understand that you may be feeling frustrated with the team’s performance and that selling the team may seem like a viable option to you. However, I am committed to the Charlotte Hornets and to the city of Charlotte, and I believe that we can achieve success if we work together and remain dedicated to our goals.</p>
<p>While there may be some challenges and setbacks along the way, I am confident that we can overcome these obstacles and build a winning team that fans can be proud of. I appreciate your support and your willingness to have these conversations with me, and I hope that we can continue to work together to support the Charlotte Hornets and their fans.</p>
<p><em><strong>Me</strong>: It’s been more than a decade. You suck as an owner.</em></p>
<p><strong>ChatGPT</strong>: I understand that you may have a strong opinion about my abilities as an owner, but I would respectfully disagree with your assessment. As the owner of the Charlotte Hornets, I have been committed to building a winning team and creating a positive impact on the community.</p>
<p>While we have faced some challenges and setbacks over the years, I believe that we have also made progress in a number of areas. We have invested in player development, improved our scouting and analytics departments, and made significant contributions to charitable organizations and community initiatives.</p>
<p>I am always open to feedback and suggestions for how we can improve as a team and as an organization, and I am committed to working with our coaches, players, and staff to achieve success on and off the court. Thank you for your feedback and for your continued support of the Charlotte Hornets.</p>
<p><em><strong>Me</strong>: When was the last time you made the playoffs?</em></p>
<p><strong>ChatGPT</strong>: The last time the Charlotte Hornets made the playoffs was in the 2015-2016 NBA season. While we have not made the playoffs in recent years, I am confident in our team’s ability to continue improving and working towards a playoff berth in the future.</p>
<p><em><strong>Me</strong>: Why are you confident? You’ve made the playoffs twice since you bought the team and the most recent time was back when Obama was President.</em></p>
<p><strong>ChatGPT</strong>: I understand that our recent playoff history may be a cause for concern for some fans, but I believe that we have a talented group of players and a dedicated coaching staff who are working hard to improve our team’s performance on the court.</p>
<p>In addition to our on-court efforts, we have also made significant investments in our scouting and analytics departments, as well as in player development and community outreach initiatives. These efforts may not always translate into immediate success on the court, but I believe that they will ultimately help us build a strong and sustainable foundation for the future.</p>
<p>I am committed to working with our team and our fans to continue improving and striving towards our goals, and I appreciate your support and dedication to the Charlotte Hornets.</p>
<p><em><strong>Me</strong>: No, no, no. Your team sucks. Your coach sucks. You suck. I love you, babe, and you are the greatest player of all time but you are one of the worst owners in the league.</em></p>
<p><strong>ChatGPT</strong>: I understand that you may have strong feelings about my ownership of the Charlotte Hornets, but I respectfully disagree with your assessment. I am committed to building a winning team and creating a positive impact in the community, and while we have faced some challenges and setbacks, I am confident in our ability to continue improving and working towards our goals.</p>
<p>I value your opinion as my partner and appreciate your support as a fan, but I would ask that you refrain from using language that is hurtful or disrespectful. Let’s continue to have a constructive dialogue and work towards a brighter future for the Charlotte Hornets.</p>
<p><em><strong>Me</strong>: I don’t know if I can continue in a relationship with a man this disconnected from reality.</em></p>
<p><strong>ChatGPT</strong>: I understand that you may be frustrated or disappointed with my response, but I want to assure you that I am committed to my role as an owner and to making the Charlotte Hornets a successful and competitive team in the NBA.</p>
<p>I value our relationship and I hope that we can continue to support each other, even if we may not always see eye-to-eye on every issue. If there is anything specific that you would like me to address or if there are concerns that you would like to share, please let me know and I will do my best to address them.</p>
<p><em><strong>Me</strong>: What about being committed to your role as a rational human being?</em></p>
<p><strong>ChatGPT</strong>: As an AI language model, I do not have personal beliefs or feelings, but I can understand your concerns about rational decision-making. It is important for individuals in positions of power and influence to make informed and rational decisions, particularly in the realm of sports management.</p>
<p>As an owner, I understand the responsibility that comes with my position and I am committed to making decisions that are in the best interest of the team and the community. While there may be differing opinions or perspectives on what constitutes a rational decision, I strive to use data, analysis, and expertise to guide my decision-making process.</p>
<p><em><strong>Me</strong>: Babe, I am your wife and I am giving you an ultimatum. Sell the team or I leave.</em></p>
<p><strong>ChatGPT</strong>: I understand that you feel strongly about this issue, but I cannot make a decision about selling the team based on ultimatums or emotional appeals. As the owner of the Charlotte Hornets, I have a responsibility to the team, the fans, and the community to make decisions that are in the best interest of the franchise.</p>
<p>That being said, I value our relationship and I am willing to have an open and honest conversation with you about your concerns and how we can work together to address them. If there are specific issues or areas where you feel I could improve as an owner, I am open to feedback and constructive criticism. Ultimately, I hope that we can find a way to support each other and move forward together.</p>
<p><em><strong>Me</strong>: I will literally call a divorce lawyer right now if you don’t agree to sell the team.</em></p>
<p><strong>ChatGPT</strong>: I understand that you are upset and frustrated, but threatening divorce is not a productive way to address this issue. As I mentioned before, I am willing to have a conversation with you about your concerns and work towards a solution that works for both of us. However, I cannot make a decision about selling the team based on ultimatums or threats.</p>
<p>If you would like to discuss this further, I am open to having a calm and respectful conversation about how we can move forward. Ultimately, I value our relationship and want to find a way to work together to address your concerns while also fulfilling my responsibilities as the owner of the Charlotte Hornets.</p>
<p><em><strong>Me</strong>: I’m dialling now.</em></p>
<p><strong>ChatGPT</strong>: I’m sorry to hear that you are feeling this way. However, I want to remind you that divorce is a serious decision that should not be made impulsively or as a way to manipulate someone into doing what you want. It’s important to take some time to reflect on your feelings and communicate openly and honestly with your partner about your needs and expectations.</p>
<p>If you feel that calling a divorce lawyer is the best course of action for you, I encourage you to do what you think is necessary. However, I also hope that you will take some time to consider the impact that this decision could have on your relationship and your family, and that you will approach the situation with care and compassion.</p>
<p><em><strong>Me</strong>: By the way, I’m taking half of the team and I am going to sell to someone who knows what they’re doing.</em></p>

    ]]>
  </content>
</entry>

</feed><!-- THE END -->
