<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	 xmlns:friends="wordpress-plugin-friends:feed-additions:1" >

<channel>
	<title>Alex Kirk</title>
	<atom:link href="https://alex.kirk.at/feed/" rel="self" type="application/rss+xml" />
	<link>https://alex.kirk.at</link>
	<description></description>
	<lastBuildDate>Wed, 25 Mar 2026 18:15:21 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.9.4</generator>

<image>
	<url>https://alex.kirk.at/wp-content/uploads/sites/2/2025/06/cropped-2025.Alex-512x512-1-150x150.jpg</url>
	<title>Alex Kirk</title>
	<link>https://alex.kirk.at</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>Friends 4.0</title>
		<link>https://alex.kirk.at/2026/03/25/friends-4-0/</link>
					<comments>https://alex.kirk.at/2026/03/25/friends-4-0/#respond</comments>
		
		<dc:creator><![CDATA[Alex Kirk]]></dc:creator>
		<pubDate>Wed, 25 Mar 2026 13:15:41 +0000</pubDate>
				<category><![CDATA[Enable Mastodon Apps]]></category>
		<category><![CDATA[Friends Plugin]]></category>
		<category><![CDATA[WordPress]]></category>
		<guid isPermaLink="false">https://alex.kirk.at/?p=3247868</guid>

					<description><![CDATA[It has been baking for much longer than I wanted, but today I released the next major version of my Friends Plugin for WordPress. Focusing on ActivityPub The biggest change is a deviation from the original idea: Friendships between WordPresses have been removed. With ActivityPub (when the respective ActivityPub plugin is installed, too) we have [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p>It has been baking for much longer than I wanted, but today I released the next major version of my <a href="https://wordpress.org/plugins/friends/">Friends Plugin for WordPress</a>.</p>



<h3 class="wp-block-heading">Focusing on ActivityPub</h3>



<p>The biggest change is a deviation from the original idea: Friendships between WordPresses have been removed. With ActivityPub (when the respective <a href="https://wordpress.org/plugins/activitypub/">ActivityPub plugin</a> is installed, too) we have a communication protocol that is supported by many more platforms than just other WordPresses that also happen to have installed the Friends plugin.</p>



<p>Removing friendship functionality reduces a lot of complexity in the plugin that changed some fundamentals of WordPress. The friendship functionality had been deactivated for a while behind a checkbox.</p>



<p>This means that the Friends plugin now focusses on functionality of subscribing to feeds (be it RSS, Atom or ActivityPub) and integrating outward communication via ActivityPub (direct messages, replies).</p>



<h3 class="wp-block-heading">Themes</h3>



<p>To make the consuming more attractive, I have worked on providing more integrated themes. I had <a href="https://github.com/akirk/friends/wiki/Writing-Themes">added the ability to contribute themes</a> already some time ago, thanks for the <a href="https://github.com/alquimidia/fedipress">FediPress theme</a> contribution! Being more a developer than a designer, my <strong>default Friends theme</strong> has been deemed more functional than pretty (from what I heard).</p>



<figure class="wp-block-image size-large"><img fetchpriority="high" decoding="async" width="1024" height="463" src="https://alex.kirk.at/wp-content/uploads/sites/2/2026/03/friends-default-theme-1024x463.png" alt="" class="wp-image-3247948" srcset="https://alex.kirk.at/wp-content/uploads/sites/2/2026/03/friends-default-theme-1024x463.png 1024w, https://alex.kirk.at/wp-content/uploads/sites/2/2026/03/friends-default-theme-655x296.png 655w, https://alex.kirk.at/wp-content/uploads/sites/2/2026/03/friends-default-theme-768x347.png 768w, https://alex.kirk.at/wp-content/uploads/sites/2/2026/03/friends-default-theme.png 1177w" sizes="(max-width: 1024px) 100vw, 1024px" /><figcaption class="wp-element-caption">Default theme</figcaption></figure>



<p>So, the new themes are:</p>



<p>A <strong>Block Theme</strong>, which allows you to modify the Friends page using the Site Editor and gives it the design of your own site&#8217;s theme.</p>



<figure class="wp-block-image size-large"><img decoding="async" width="1024" height="456" src="https://alex.kirk.at/wp-content/uploads/sites/2/2026/03/friends-block-theme-1024x456.png" alt="" class="wp-image-3247949" srcset="https://alex.kirk.at/wp-content/uploads/sites/2/2026/03/friends-block-theme-1024x456.png 1024w, https://alex.kirk.at/wp-content/uploads/sites/2/2026/03/friends-block-theme-655x292.png 655w, https://alex.kirk.at/wp-content/uploads/sites/2/2026/03/friends-block-theme-768x342.png 768w, https://alex.kirk.at/wp-content/uploads/sites/2/2026/03/friends-block-theme.png 1175w" sizes="(max-width: 1024px) 100vw, 1024px" /><figcaption class="wp-element-caption">Block Theme</figcaption></figure>



<p>A <strong>Google Reader Theme</strong> makes it look like Google Reader. This comes with keyboard shortcuts and the accordion-like behavior of the posts.</p>



<figure class="wp-block-image size-large"><img decoding="async" width="1024" height="414" src="https://alex.kirk.at/wp-content/uploads/sites/2/2026/03/friends-google-reader-1024x414.png" alt="" class="wp-image-3247950" srcset="https://alex.kirk.at/wp-content/uploads/sites/2/2026/03/friends-google-reader-1024x414.png 1024w, https://alex.kirk.at/wp-content/uploads/sites/2/2026/03/friends-google-reader-655x265.png 655w, https://alex.kirk.at/wp-content/uploads/sites/2/2026/03/friends-google-reader-768x310.png 768w, https://alex.kirk.at/wp-content/uploads/sites/2/2026/03/friends-google-reader.png 1176w" sizes="(max-width: 1024px) 100vw, 1024px" /><figcaption class="wp-element-caption">Google Reader Theme</figcaption></figure>



<p>I had already done a <a href="https://github.com/akirk/friends-mastodon-like-interface">prototype</a> of a <strong>Mastodon Theme</strong> and have now added a functional one that is shipped by default.</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="415" src="https://alex.kirk.at/wp-content/uploads/sites/2/2026/03/friends-mastodon-1024x415.png" alt="" class="wp-image-3247954" srcset="https://alex.kirk.at/wp-content/uploads/sites/2/2026/03/friends-mastodon-1024x415.png 1024w, https://alex.kirk.at/wp-content/uploads/sites/2/2026/03/friends-mastodon-655x265.png 655w, https://alex.kirk.at/wp-content/uploads/sites/2/2026/03/friends-mastodon-768x311.png 768w, https://alex.kirk.at/wp-content/uploads/sites/2/2026/03/friends-mastodon.png 1160w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /><figcaption class="wp-element-caption">Mastodon Theme</figcaption></figure>



<p>All the themes now support light and dark mode (which makes the Mastodon theme look a bit unusual in light mode).</p>



<p>I hope that the screenshots above highlight the versatility of the plugin and how much the visual appearance can shape the perception.</p>



<h3 class="wp-block-heading">Migrations</h3>



<p>A big reason for the 4.0 version number was the number of migrations of internal data structures towards more taxonomies (the Friends plugin did not and does not use custom tables). This removes the last bits of supporting WordPress users as friend users and adds proper term relationships between friends and subscriptions. This also allowed to add support for folders.</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="147" src="https://alex.kirk.at/wp-content/uploads/sites/2/2026/03/friends-4.0-notification-1024x147.png" alt="" class="wp-image-3247959" srcset="https://alex.kirk.at/wp-content/uploads/sites/2/2026/03/friends-4.0-notification-1024x147.png 1024w, https://alex.kirk.at/wp-content/uploads/sites/2/2026/03/friends-4.0-notification-655x94.png 655w, https://alex.kirk.at/wp-content/uploads/sites/2/2026/03/friends-4.0-notification-768x110.png 768w, https://alex.kirk.at/wp-content/uploads/sites/2/2026/03/friends-4.0-notification.png 1308w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<p>But it makes a transition from an earlier version potentially a bit tricky. With this amount of changes and migrations, I opted to make it easier to discover what&#8217;s new and what is already migrated. I hope that all migrations go smoothly but if they don&#8217;t, this gives you insight into where things might be stuck. </p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="567" height="1024" src="https://alex.kirk.at/wp-content/uploads/sites/2/2026/03/friends-news-567x1024.png" alt="" class="wp-image-3247968" srcset="https://alex.kirk.at/wp-content/uploads/sites/2/2026/03/friends-news-567x1024.png 567w, https://alex.kirk.at/wp-content/uploads/sites/2/2026/03/friends-news-443x800.png 443w, https://alex.kirk.at/wp-content/uploads/sites/2/2026/03/friends-news-768x1386.png 768w, https://alex.kirk.at/wp-content/uploads/sites/2/2026/03/friends-news-851x1536.png 851w, https://alex.kirk.at/wp-content/uploads/sites/2/2026/03/friends-news-1135x2048.png 1135w, https://alex.kirk.at/wp-content/uploads/sites/2/2026/03/friends-news.png 1180w" sizes="auto, (max-width: 567px) 100vw, 567px" /></figure>



<p>The amount of necessary fundamental changes and migrations made this release somewhat risky and was a reason for the long time since the last release. I am hoping that with these changes now shipped, I can provide more frequent updates again!</p>



<p>Oh, I also shipped a new version of the <a href="https://wordpress.org/plugins/enable-mastodon-apps/">Enable Mastodon Apps plugin</a> (1.5.0) which makes use of some of the taxonomy changes in Friends that now allow to distinguish between mentions and direct messages, and there should be a speed-up in many endpoints, especially the notifications endpoint.</p>



<p>Enjoy this new release, which I hope will make it easier and more feasible to use <a href="https://alex.kirk.at/2024/06/13/your-wordpress-as-your-personal-mastodon-instance/">Your WordPress as Your Personal Mastodon Instance</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://alex.kirk.at/2026/03/25/friends-4-0/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<friends:post-format>standard</friends:post-format>
	</item>
		<item>
		<title>WordPress Development Without a Computer</title>
		<link>https://alex.kirk.at/2025/11/29/wordpress-development-without-a-computer/</link>
					<comments>https://alex.kirk.at/2025/11/29/wordpress-development-without-a-computer/#comments</comments>
		
		<dc:creator><![CDATA[Alex Kirk]]></dc:creator>
		<pubDate>Sat, 29 Nov 2025 06:27:14 +0000</pubDate>
				<category><![CDATA[AI]]></category>
		<category><![CDATA[Code]]></category>
		<category><![CDATA[Playground]]></category>
		<category><![CDATA[playground]]></category>
		<category><![CDATA[Step Library]]></category>
		<category><![CDATA[WordPress]]></category>
		<guid isPermaLink="false">https://alex.kirk.at/?p=2937002</guid>

					<description><![CDATA[With AI coding assistants and WordPress Playground, you can now develop WordPress plugins from your phone. Here's how to set it up.]]></description>
										<content:encoded><![CDATA[
<p>You&#8217;re on the train, scrolling through your WordPress site on your phone, and you see an issue that you&#8217;d like to fix, for example improvement to the mobile view. Normally you&#8217;d make a (mental) note and deal with it when you&#8217;re back at your computer.</p>



<p>But what if you could just fix it right there?</p>



<p>With AI coding assistants that run in the browser—like <a href="https://claude.ai/code">Claude Code</a>, <a href="https://openai.com/codex/">OpenAI Codex</a>, <a href="https://githubnext.com/projects/copilot-workspace">GitHub Copilot Workspace</a>, or similar tools—combined with <a href="https://playground.wordpress.net/">WordPress Playground</a> for testing, you can now do WordPress plugin development without a computer.</p>



<h2 class="wp-block-heading">What It Looks Like</h2>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p>AI: I&#8217;ve implemented the fix for you, committed and pushed it to Github. Use this link to <a href="https://playground.wordpress.net/">Test it in WordPress Playground</a>.</p>
</blockquote>



<p>This link above just leads to a generic Playground but to give you an idea of the workflow: The AI helps you fix or implement what you asked for and makes the code available in a branch. You&#8217;ll then run/view it via Playground. Here&#8217;s how to set this up:</p>



<h2 class="wp-block-heading">What You Need</h2>



<ul class="wp-block-list">
<li>Your plugin or theme in a GitHub repository,</li>



<li>A web AI coding assistant,</li>



<li>A way to tell the AI how to generate Playground test links that you can click.</li>
</ul>



<p>The third part is where the <a href="https://akirk.github.io/playground-step-library/">Playground Step Library</a> comes in.</p>



<h2 class="wp-block-heading">Step 1: Create Your Blueprint</h2>



<p>WordPress Playground uses <a href="https://wordpress.github.io/wordpress-playground/blueprints-api/index/">blueprints</a>: JSON configurations that describe what to install and how to set things up. You can install plugins, themes, configure settings, import content, and more. Writing these by hand is a little cumbersome, so I built the Step Library as a visual tool to assemble blueprints step by step.</p>



<p>The Step Library also provides more steps than Playground offers natively: that&#8217;s where the name comes from. It compiles these custom steps into the native steps that Playground understands. The native steps are powerful but require you to know how to combine them in clever ways; the Step Library&#8217;s <a href="https://github.com/akirk/playground-step-library/tree/main/docs">custom steps</a> make it easier. Examples include <a href="https://github.com/akirk/playground-step-library/blob/main/docs/steps/addProduct.md">addProduct</a> for WooCommerce, <a href="https://github.com/akirk/playground-step-library/blob/main/docs/steps/addTemplatePart.md">addTemplatePart</a> for block themes, a <a href="https://github.com/akirk/playground-step-library/blob/main/docs/steps/debug.md">debug</a> step to enable common debug settings and plugins, or <a href="https://github.com/akirk/playground-step-library/blob/main/docs/steps/disableWelcomeGuides.md">disableWelcomeGuides</a>.</p>



<p>Use <a href="https://akirk.github.io/playground-step-library/?step%5B0%5D=installPlugin">this special link to the Step Library</a> to start with an <a href="https://github.com/akirk/playground-step-library/blob/main/docs/steps/installPlugin.md">&#8220;Install Plugin&#8221; step</a>. Paste your HTTPS GitHub repository URL. If you want to test a specific branch, add <code>/tree/branch-name</code> to the URL—but for now, just use your main branch. We&#8217;ll make the branch dynamic later.</p>



<p>Add any other steps your testing environment needs: maybe WooCommerce if your plugin integrates with it, or some test content, or specific WordPress settings.</p>



<h2 class="wp-block-heading">Step 2: Generate AI Instructions</h2>



<p>Once your blueprint is ready, open the &#8220;Copy/Share&#8221; dropdown and select &#8220;Generate AI Instructions&#8221;. This creates a markdown snippet you can add to your project&#8217;s <code>CLAUDE.md</code>, <code>.github/copilot-instructions.md</code>, or similar AI instruction file:</p>



<figure class="wp-block-image size-full is-resized"><img loading="lazy" decoding="async" width="674" height="568" src="https://alex.kirk.at/wp-content/uploads/sites/2/2025/11/copy-dropdown-menu.png" alt="" class="wp-image-2937025" style="width:271px;height:auto" srcset="https://alex.kirk.at/wp-content/uploads/sites/2/2025/11/copy-dropdown-menu.png 674w, https://alex.kirk.at/wp-content/uploads/sites/2/2025/11/copy-dropdown-menu-655x552.png 655w" sizes="auto, (max-width: 674px) 100vw, 674px" /></figure>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="929" src="https://alex.kirk.at/wp-content/uploads/sites/2/2025/11/generate-ai-instructions-1024x929.png" alt="" class="wp-image-2937024" srcset="https://alex.kirk.at/wp-content/uploads/sites/2/2025/11/generate-ai-instructions-1024x929.png 1024w, https://alex.kirk.at/wp-content/uploads/sites/2/2025/11/generate-ai-instructions-655x594.png 655w, https://alex.kirk.at/wp-content/uploads/sites/2/2025/11/generate-ai-instructions-768x696.png 768w, https://alex.kirk.at/wp-content/uploads/sites/2/2025/11/generate-ai-instructions-1536x1393.png 1536w, https://alex.kirk.at/wp-content/uploads/sites/2/2025/11/generate-ai-instructions.png 1630w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<p>The generated instructions tell the AI to include a Playground testing link at the end of its responses. The branch name in your URL gets replaced with a <code>BRANCH_NAME</code> placeholder, so the AI knows to substitute the actual branch it&#8217;s working on.</p>



<h2 class="wp-block-heading">Step 3: Add to Your Repository</h2>



<p>Copy the generated markdown and add it to your AI instruction file. Commit it to your repository. Now any AI assistant that reads these instructions will include Playground links when it makes changes to your code.</p>



<p>Bonus: you can also instruct your coding assistant to add such a file to your repo!</p>



<h2 class="wp-block-heading">The Workflow</h2>



<p>Here&#8217;s what this looks like in practice:</p>



<ol class="wp-block-list">
<li>Open your AI coding assistant on your phone (or desktop),</li>



<li>Connect to your GitHub repository,</li>



<li>Describe what you want to change or fix,</li>



<li>The AI makes the changes and pushes a branch,</li>



<li>Tap the Playground link in the response,</li>



<li>Test the changes in Playground—if it&#8217;s a private repo, you&#8217;ll authenticate with GitHub here,</li>



<li>If it works, create a PR and merge it—you got to test before even opening the PR.</li>
</ol>



<p>It&#8217;s a complete development loop. The AI handles the code, GitHub handles version control, and Playground handles testing. Your phone is just the interface tying it all together.</p>



<h2 class="wp-block-heading">Private Repositories</h2>



<p>Until recently, this workflow only worked with public GitHub repositories. I <a href="https://github.com/WordPress/wordpress-playground/pull/2856">submitted a PR to WordPress Playground</a> that adds GitHub OAuth authentication. Now when you load a plugin from a private repository, Playground prompts you to authenticate, and then it works just like public repos.</p>



<h2 class="wp-block-heading">Beyond Mobile: Preconfigured Test Environments</h2>



<p>The mobile workflow is a fun demo, but the same setup is useful on desktop too. The real power is in the preconfigured Playground environments through <a href="https://wordpress.github.io/wordpress-playground/blueprints-api/index/">blueprints</a> (which you can easily create with the <a href="https://akirk.github.io/playground-step-library/">Step Library</a>).</p>



<p>Say your plugin integrates with <a href="https://woocommerce.com/">WooCommerce</a>. You can create a blueprint that installs WooCommerce, sets up a test product, and installs your plugin from the current branch. Now every Playground link the AI generates loads an environment where you can actually test the integration—not just whether your plugin activates without errors.</p>



<p>Or you want to test across different configurations: multisite vs single site, classic editor vs block editor, different PHP versions. Create a blueprint for each scenario, generate AI instructions for each, and you have a test matrix that&#8217;s one click away.</p>



<h2 class="wp-block-heading">GitHub Actions</h2>



<p>You can take this further with a <a href="https://wordpress.github.io/wordpress-playground/guides/github-action-pr-preview">GitHub Action that posts a Playground link &#8220;Try it in Playground&#8221; as a comment on every PR</a>. That way anyone reviewing the PR can test the changes without setting up a local environment.</p>



<p>The Step Library is available as an <a href="https://www.npmjs.com/package/playground-step-library">npm package</a>, so you can integrate it into your own tooling and CI pipelines.</p>



<h2 class="wp-block-heading">Let AI Create Blueprints for You</h2>



<p>Something often overlooked: the Step Library is also useful for getting AI to help you create blueprints in the first place. The native Playground steps are low-level—things like <code>writeFile</code> and <code>runPHP</code>—so AI assistants often don&#8217;t grasp what&#8217;s actually possible with blueprints. The Step Library&#8217;s high-level steps are more intuitive, and with a <a href="https://akirk.github.io/playground-step-library/step-library-schema.json">JSON schema</a> that describes them, AI can easily understand what&#8217;s available and generate useful blueprints.</p>



<h2 class="wp-block-heading">Other New Step Library Features</h2>



<p>Some notable other things I added recently:</p>



<p><strong><a href="https://akirk.github.io/playground-step-library/docs/importers#wp-envjson">wp-env.json import</a></strong>: Drop your <code>.wp-env.json</code> into the Step Library and it converts your local dev environment config into a Playground blueprint.</p>



<p><strong><a href="https://akirk.github.io/playground-step-library/docs/importers#plugintheme-urls">GitLab, Bitbucket, and Codeberg support</a></strong>: Not everyone uses GitHub. The Step Library now recognizes repository URLs from these platforms.</p>



<p><strong><a href="https://akirk.github.io/playground-step-library/docs/importers">Paste detection</a></strong>: Paste a plugin URL, some PHP code, or even an existing Playground URL, and the Step Library figures out what it is and creates the right steps.</p>



<h2 class="wp-block-heading">Try It</h2>



<p>The <a href="https://akirk.github.io/playground-step-library/">Playground Step Library</a> is where you can create your blueprint and generate AI instructions.</p>



<p>I&#8217;ve found myself using this on the train, in waiting rooms, wherever I have a few minutes and an idea I want to try. It&#8217;s not how I imagined WordPress development would work, but it does.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://alex.kirk.at/2025/11/29/wordpress-development-without-a-computer/feed/</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		
		<friends:post-format>standard</friends:post-format>
	</item>
		<item>
		<title></title>
		<link>https://alex.kirk.at/2025/11/12/2910911/</link>
					<comments>https://alex.kirk.at/2025/11/12/2910911/#respond</comments>
		
		<dc:creator><![CDATA[Alex Kirk]]></dc:creator>
		<pubDate>Wed, 12 Nov 2025 15:34:32 +0000</pubDate>
				<category><![CDATA[Web]]></category>
		<guid isPermaLink="false">https://alex.kirk.at/?p=2910911</guid>

					<description><![CDATA[I&#8217;ll speak about Telex and how to use Playground in your AI workflow at today&#8217;s WordPress Vienna meetup!]]></description>
										<content:encoded><![CDATA[
<p>I&#8217;ll speak about <a href="https://telex.automattic.ai/">Telex</a> and how to use Playground in your AI workflow at <a href="https://www.meetup.com/vienna-wordpress-meetup/events/311518999/">today&#8217;s WordPress Vienna meetup</a>!</p>
]]></content:encoded>
					
					<wfw:commentRss>https://alex.kirk.at/2025/11/12/2910911/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<friends:post-format>status</friends:post-format>
	</item>
		<item>
		<title>Adapting Tools to Your Needs with AI</title>
		<link>https://alex.kirk.at/2025/10/14/adapting-tools-to-your-needs-with-ai/</link>
					<comments>https://alex.kirk.at/2025/10/14/adapting-tools-to-your-needs-with-ai/#respond</comments>
		
		<dc:creator><![CDATA[Alex Kirk]]></dc:creator>
		<pubDate>Tue, 14 Oct 2025 08:54:06 +0000</pubDate>
				<category><![CDATA[Code]]></category>
		<category><![CDATA[adb]]></category>
		<category><![CDATA[Claude Code]]></category>
		<guid isPermaLink="false">https://alex.kirk.at/?p=2828314</guid>

					<description><![CDATA[These days you can just fix and adapt incomplete tools that you encounter with AI like Claude Code!]]></description>
										<content:encoded><![CDATA[
<p>In past years, as a developer, for some features or the early stages of software, writing down the code felt like a chore. You knew what to do and you had to tediously spell it out. Of course, with AI tools like <a href="https://www.claude.com/product/claude-code">Claude Code</a> (which I like in particular, the CLI approach appeals to me) this now is vastly better, and actually it&#8217;s quite easy to accidentally take it too far.</p>



<p>But here, I want to talk about something different: It happens that you search for a tool and then you come across something that almost does what you want, but not quite.</p>



<p>Before AI programming tools, you either had to be lucky to know the software stack, or it must be a really important problem to you that you would try to understand the codebase and make the modification you need.</p>



<p>Today, I can just use Claude Code to modify any tool how I like. So instead of turning away in frustration, I just ask Claude to help me fix what doesn&#8217;t work for me. How great is that?</p>



<p>A recent example for me has been transferring files to my Android Phone. <a href="https://openmtp.ganeshrvel.com/">OpenMTP</a> exists but to me it has proven to be highly unrealiable, you need to remember to not have Preview open in macOS for it to work, and recently it didn&#8217;t complete a copy process but didn&#8217;t tell me about it. I only found out on the go that some files had not been copied.</p>



<p>So I realized, that I can use <code>adb</code> to push files to my phone using the debug mode. It&#8217;s very niche, I know, but it works. And then I realized a little UI would be nice, and I discovered <a href="https://github.com/darkhz/adbtuifm">darkhz&#8217;s adbtuifm</a>. A tool written in Go but only tested on Linux, a file manager like Total Commander for the CLI that uses <code>adb</code> in the background.</p>



<p>And indeed, it didn&#8217;t really work well on macOS CLI. The left side appeared empty.</p>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="976" height="511" src="https://alex.kirk.at/wp-content/uploads/sites/2/2025/10/adbtuifm-before.png" alt="" class="wp-image-2828419" srcset="https://alex.kirk.at/wp-content/uploads/sites/2/2025/10/adbtuifm-before.png 976w, https://alex.kirk.at/wp-content/uploads/sites/2/2025/10/adbtuifm-before-655x343.png 655w, https://alex.kirk.at/wp-content/uploads/sites/2/2025/10/adbtuifm-before-768x402.png 768w" sizes="auto, (max-width: 976px) 100vw, 976px" /><figcaption class="wp-element-caption">Hardly anything readable and the left side empty</figcaption></figure>



<p>But this is what it looks like today:</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="778" src="https://alex.kirk.at/wp-content/uploads/sites/2/2025/10/adbtuifm-1024x778.png" alt="" class="wp-image-2828393" srcset="https://alex.kirk.at/wp-content/uploads/sites/2/2025/10/adbtuifm-1024x778.png 1024w, https://alex.kirk.at/wp-content/uploads/sites/2/2025/10/adbtuifm-655x498.png 655w, https://alex.kirk.at/wp-content/uploads/sites/2/2025/10/adbtuifm-768x584.png 768w, https://alex.kirk.at/wp-content/uploads/sites/2/2025/10/adbtuifm-1536x1167.png 1536w, https://alex.kirk.at/wp-content/uploads/sites/2/2025/10/adbtuifm.png 1950w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /><figcaption class="wp-element-caption">My updated version of <a href="https://github.com/akirk/adbtuifm">adbtuifm</a></figcaption></figure>



<p>So I forked it and <a href="https://github.com/darkhz/adbtuifm/compare/master...akirk:adbtuifm:main">adapted it to my needs</a>:</p>



<ul class="wp-block-list">
<li>It <a href="https://github.com/darkhz/adbtuifm/commit/e2d75de31b06cb463f8b2e5e7254920a036ceda0">now uses the current directory</a> instead of the non-existent-on-macOS <code>/home</code>.</li>



<li><a href="https://github.com/darkhz/adbtuifm/commit/df5eafb6ecfb0e6af09b339d2428a633555adc3a">Fixed the colors</a> so that things are also readable in light mode.</li>



<li><a href="https://github.com/darkhz/adbtuifm/commit/d92b3224f5058d5b32af00fffd2d091c3d231111">Introduced an ADB log pane</a> to see what&#8217;s going on behind the scenes.</li>



<li>It now <a href="https://github.com/darkhz/adbtuifm/commit/d0fb25fe438f4fec12119e9caeaf78d707d1d031">shows size and last modification dates</a>.</li>



<li>Introduced <a href="https://github.com/darkhz/adbtuifm/commit/77731d3293b14850250707d82d3d83b904d89650">history navigation</a>.</li>



<li>Even <a href="https://github.com/darkhz/adbtuifm/commit/05344a29073b6bc18f1856c4f2d70add943d55ea">fixed a (tricky?) UI hang</a> when deleting files.</li>
</ul>



<p>The most important change for me probably was the first one, and, ok, I could have probably just changed the hardcoded string myself. </p>



<p>But it was such a joy to continue and make the tool nicer to use! Also, I don&#8217;t think I could have fixed that hanging UI before wasting too much time.</p>



<p>You can <a href="https://github.com/akirk/adbtuifm">try my version</a>, and maybe fork it and add more things you like yourself? I could send back a PR but maybe I won&#8217;t do it this time because my changes are opinionated and the repo <a href="https://github.com/darkhz/adbtuifm">seems abandoned</a> with the last change in 2022.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://alex.kirk.at/2025/10/14/adapting-tools-to-your-needs-with-ai/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<friends:post-format>standard</friends:post-format>
	</item>
		<item>
		<title>Proposal: an Interactive Mode for phpcbf</title>
		<link>https://alex.kirk.at/2025/09/29/proposal-an-interactive-mode-for-phpcbf/</link>
					<comments>https://alex.kirk.at/2025/09/29/proposal-an-interactive-mode-for-phpcbf/#respond</comments>
		
		<dc:creator><![CDATA[Alex Kirk]]></dc:creator>
		<pubDate>Mon, 29 Sep 2025 12:05:06 +0000</pubDate>
				<category><![CDATA[Code]]></category>
		<category><![CDATA[PHP]]></category>
		<guid isPermaLink="false">https://alex.kirk.at/?p=2814422</guid>

					<description><![CDATA[It can be very time consuming to resolve issues detected by PHP Code Sniffer. An interactive mode for phpcbf could make things much faster!]]></description>
										<content:encoded><![CDATA[
<p>Did you ever get a little annoyed at <code>phpcs</code>? Maybe you&#8217;re like me: I like the idea of <a href="https://github.com/phpcsstandards/PHP_CodeSniffer">PHP Code Sniffer</a> (phpcs), but I think the user experience has room for improvement:</p>



<p>Especially when trying to get larger amounts of PHP code to comply with the coding standards, it feels like this tool just scolds you and all you can do is to diligently work away on each and every violation that it discovers.</p>



<p>And you might have gotten yourself into such a situation because <a href="https://github.com/akirk/friends/pull/329">you realized well into the project that you forgot an important ruleset</a>, or when you&#8217;re merging codebases.</p>



<h3 class="wp-block-heading">Sniffs are Opinions</h3>



<p>One important thing that we tend to forget: often we are in a position where we can actually make the decisions which rules to follow and which not. A ruleset prepared by someone else might contain things we disagree with. Thus phpcs contains the ability to exclude sniffs via its phpcs.xml configuration file, and I think it&#8217;s ok to make use of that. But also, I think that phpcs could be more helpful to you in doing so.</p>



<p>When you encounter such an overly eager ruleset, you might complain that the ruleset itself should be updated. But maybe you are not in a position to fight that battle, so you can just find a solution for yourself.</p>



<h3 class="wp-block-heading">phpcbf can help fix things</h3>



<p>The PHP Code Sniffer project comes with two main executables: <code>phpcs</code>, and <code>phpcbf</code>. While <code>phpcs</code> complains, <code>phpcbf</code> tries to help you. Sniffs can provide auto-fixers for violations they encounter and <code>phpcbf</code> applies them for you. But oftentimes it seems like there should be an auto-fixer but in the end, you have to fix it yourself.</p>



<p>A side-note here: maintaining the phpcs project is certainly not a piece of cake since it&#8217;s a project heavily exposed to opinion. Many things have to be considered, and it looks like there has been agreement that an auto-fixer can only be added if there is a single and clear solution to the problem.</p>



<p>Thus, there are a number of sniffs where the resolution of a violation needs a user decision. This decision could be complex, like you need to rearrange code, or add something that you forgot (like a type for a parameter). But I believe there are also decisions to make where it&#8217;s a matter of choosing between several options.</p>



<h3 class="wp-block-heading">User Decision Required</h3>



<p>One example of this is <code>Squiz.Commenting.InlineComment.InvalidEndChar</code>: &#8220;Inline comments must end in full-stops, exclamation marks, or question marks.&#8221; Let&#8217;s not argue about its validity but about the reason it cannot be auto-fixed: There are multiple valid end chars and an auto-fixer cannot know which one is the right one here.</p>



<p>So, what happens if we make <code>phpcbf</code> interactive, so that it can ask the user to select one of the potential fixes, and then just goes ahead and makes them?</p>



<p>Or, if you realize that you disagree with this sniff: what if <code>phpcbf</code> will just quickly add an <code>&lt;exclude ref="Sniff.Name"/&gt;</code> to your <code>phpcs.xml</code>? Or it could help you just disable the rule for the file? Or just ignore this line?</p>



<p>Many IDEs actually already have some of these ways of dealing with violations, <a href="https://www.jetbrains.com/help/phpstorm/using-php-code-sniffer.html#fixing-issues">either natively</a> or <a href="https://github.com/sdobreff/vscode-php-resolver/blob/main/README.md#phpcs-rules-ignore">through an extension</a>. Bringing them to phpcbf itself would make this available to a wider audience and solutions could be baked in to sniffs.</p>



<h3 class="wp-block-heading">Interactive Mode</h3>



<p>All of these thoughts culminate in this idea to make <code>phpcbf</code> interactive. I didn&#8217;t know until recently that phpcs has an interactive mode, too. But all it does is to process a file and pauses to allow the user to edit the file, and then to process it again. It assists you in checking, but not in fixing.</p>



<p>So, here is how this could work. Let&#8217;s assume this <code>test.php</code>:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: php; title: ; notranslate">
&lt;?php

//helo
class test
{
echo &#039;hello&#039;;
}
</pre></div>


<p>This file has some problems as <code>phpcs</code> tells you (the selection of Sniffs here is a bit arbitrary but to show the variety of options we&#8217;ll face):</p>


<div class="wp-block-syntaxhighlighter-code ">
\e[1mFILE: test.php\e[0m
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-
\e[1mFOUND 6 ERRORS AFFECTING 4 LINES\e[0m
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-
 1 | \e[31mERROR\e[0m | [ ] You must use &#8220;/**&#8221; style comments for a file comment
 3 | \e[31mERROR\e[0m | [x] No space found before comment text; expected &#8220;// helo&#8221; but found &#8220;//helo&#8221;
 3 | \e[31mERROR\e[0m | [ ] Inline comments must start with a capital letter
 3 | \e[31mERROR\e[0m | [ ] Inline comments must end in full-stops, exclamation marks, or question marks
 4 | \e[31mERROR\e[0m | [ ] Test name must begin with a capital letter
 6 | \e[31mERROR\e[0m | [x] Line indented incorrectly; expected at least 4 spaces, found 0
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-
\e[1mPHPCBF CAN FIX THE 2 MARKED SNIFF VIOLATIONS AUTOMATICALLY\e[0m
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-

</div>


<p>As you can see, some violations can be fixed, most cannot. The reason for those is that there is no auto-fixer implemented for them, and often the reason is that there is no one-and-only-way to fix this.</p>



<p>So let&#8217;s see how interactive mode would work here. In this first case I&#8217;d like to show a situation where there is no auto-fixer available. These would be the options:</p>


<div class="wp-block-syntaxhighlighter-code ">
[1mPHPCBF INTERACTIVE MODE &#8211; test.php[0m

[33mERRORS[0m at line 1, column 6:
  You must use &#8220;/**&#8221; style comments for a file comment
  Sniff: PEAR.Commenting.FileComment.WrongStyle
  [31m(Not auto-fixable)[0m

      [33m  1> &lt;?php[0m
      [90m  2  [0m
      [90m  3  //helo[0m
Choose an action:
  [i] Add a phpcs:ignore to this line (phpcs:ignore)
  [d] Disable this sniff for this file (phpcs:disable)
  [p] Project-wide: exclude this sniff in phpcs.xml
  [e] Edit the file manually
  [s] Skip this violation
  [q] Quit
Action (default: edit):
</div>


<p>Now let&#8217;s look at a case where an auto-fixer is available. In non-interactive mode, <code>phpcbf</code> would just fix it, but here you have the option to skip it, too. It would be nice if it even could preview the auto-fix:</p>


<div class="wp-block-syntaxhighlighter-code ">
[33mERRORS[0m at line 6, column 1:
  Line indented incorrectly; expected at least 4 spaces, found 0
  Sniff: Generic.WhiteSpace.ScopeIndent.Incorrect
  [32m(Auto-fixable)[0m

      [90m  4  class test[0m
      [90m  5  {[0m
      [31m  6- echo &#8216;hello&#8217;;[0m
      [32m  6+      echo &#8216;hello&#8217;;[0m
      [90m  7  }[0m
      [90m  8  [0m
Choose an action:
  [f] Fix automatically
  [i] Add a phpcs:ignore to this line (phpcs:ignore)
  [d] Disable this sniff for this file (phpcs:disable)
  [p] Project-wide: exclude this sniff in phpcs.xml
  [e] Edit the file manually
  [s] Skip this violation
  [q] Quit
Action (default: auto-fix):
</div>


<p>Now let&#8217;s look come back to our example from above where it seems like an auto-fixer could exist but it does not because there are multiple ways to fix it. For this one, we&#8217;d have an interactive fixer that gives the user the choice how to fix it:</p>


<div class="wp-block-syntaxhighlighter-code ">
[33mERRORS[0m at line 3, column 1:
  Inline comments must end in full-stops, exclamation marks, or question marks
  Sniff: Squiz.Commenting.InlineComment.InvalidEndChar
  [36m(Interactive fixes available)[0m

[1mInteractive Fix Options:[0m
  [1] Append a .
      [90m  1  &lt;?php[0m
      [90m  2  [0m
      [31m  3- // Helo[0m
      [32m  3+ // Helo.[0m
      [90m  4  class test[0m
      [90m  5  {[0m
  [2] Append a !
      [90m  1  &lt;?php[0m
      [90m  2  [0m
      [31m  3- // Helo[0m
      [32m  3+ // Helo![0m
      [90m  4  class test[0m
      [90m  5  {[0m
  [3] Append a ?
      [90m  1  &lt;?php[0m
      [90m  2  [0m
      [31m  3- // Helo[0m
      [32m  3+ // Helo?[0m
      [90m  4  class test[0m
      [90m  5  {[0m
  [4] Remove comment
      [90m  1  &lt;?php[0m
      [90m  2  [0m
      [31m  3- // Helo[0m
      [90m  4  class test[0m
      [90m  5  {[0m

Choose an action:
  [1] Apply: Append a .
  [2] Apply: Append a !
  [3] Apply: Append a ?
  [4] Apply: Remove comment
  [i] Add a phpcs:ignore to this line (phpcs:ignore)
  [d] Disable this sniff for this file (phpcs:disable)
  [p] Project-wide: exclude this sniff in phpcs.xml
  [e] Edit the file manually
  [s] Skip this violation
  [q] Quit
Action (default: 1 &#8220;Append a .&#8221;):
</div>


<p>One could argue that you can do all of this today but I think with such an interactive mode we can relieve much of the pain it causes to get a code base to comply by streamlining what you need to do already today anyway: go through each violation and try to fix it.</p>



<p>Some of the choices I haven&#8217;t described yet:</p>



<ul class="wp-block-list">
<li><code>i</code> would just append a <code>// phpcs:ignore Sniff.Name</code> to the line.</li>



<li><code>d</code> would add a <code>// phpcs:disable Sniff.Name</code> at the beginning of the file.</li>



<li><code>p</code> would add an <code>&lt;exclude ref="Sniff.Name"/&gt;</code> to your <code>phpcs.xml</code>.</li>



<li><code>e</code> would open an editor at the line of the code</li>
</ul>



<p>In summary, this is a proposal to improve the user experience. I think this could transform an experience where <code>phpcs</code> is the tool that scolds you, to the tool that assists you in unifying a codebase to certain standards.</p>



<details class="wp-block-details is-layout-flow wp-block-details-is-layout-flow"><summary>Finally, expand this to see the whole run-down of an interactive <code>phpcbf -a</code> session.</summary><div class="wp-block-syntaxhighlighter-code ">
❯ bat test.php
[38;5;246m───────┬────────────────────────────────────────────────────────────────────────[0m
       [38;5;246m│ [0mFile: [1mtest.php[0m
[38;5;246m───────┼────────────────────────────────────────────────────────────────────────[0m
[38;5;246m   1[0m   [38;5;246m│[0m [38;5;231m&lt;?php[0m
[38;5;246m   2[0m   [38;5;246m│[0m 
[38;5;246m   3[0m   [38;5;246m│[0m [38;5;242m//[0m[38;5;242mhelo[0m
[38;5;246m   4[0m   [38;5;246m│[0m [38;5;149mclass[0m[38;5;231m [0m[4;38;5;81mtest[0m
[38;5;246m   5[0m   [38;5;246m│[0m [38;5;231m{[0m
[38;5;246m   6[0m   [38;5;246m│[0m [38;5;167mecho[0m[38;5;231m [0m[38;5;186m&#8217;[0m[38;5;186mhello[0m[38;5;186m&#8217;[0m[38;5;231m;[0m
[38;5;246m   7[0m   [38;5;246m│[0m [38;5;231m}[0m
[38;5;246m───────┴────────────────────────────────────────────────────────────────────────[0m
❯ ./bin/phpcs test.php

[1mFILE: test.php[0m
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-
[1mFOUND 6 ERRORS AFFECTING 4 LINES[0m
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-
 1 | [31mERROR[0m | [ ] You must use &#8220;/**&#8221; style comments for a file comment
 3 | [31mERROR[0m | [x] No space found before comment text; expected &#8220;// helo&#8221; but found &#8220;//helo&#8221;
 3 | [31mERROR[0m | [ ] Inline comments must start with a capital letter
 3 | [31mERROR[0m | [ ] Inline comments must end in full-stops, exclamation marks, or question marks
 4 | [31mERROR[0m | [ ] Test name must begin with a capital letter
 6 | [31mERROR[0m | [x] Line indented incorrectly; expected at least 4 spaces, found 0
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-
[1mPHPCBF CAN FIX THE 2 MARKED SNIFF VIOLATIONS AUTOMATICALLY[0m
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-

❯ ./bin/phpcbf -a test.php
[1mPHPCBF INTERACTIVE MODE &#8211; test.php[0m

[33mERRORS[0m at line 1, column 6:
  You must use &#8220;/**&#8221; style comments for a file comment
  Sniff: PEAR.Commenting.FileComment.WrongStyle
  [31m(Not auto-fixable)[0m

      [33m  1> &lt;?php[0m
      [90m  2  [0m
      [90m  3  //helo[0m
Choose an action:
  [i] Add a phpcs:ignore to this line (phpcs:ignore)
  [d] Disable this sniff for this file (phpcs:disable)
  [p] Project-wide: exclude this sniff in phpcs.xml
  [e] Edit the file manually
  [s] Skip this violation
  [q] Quit
Action (default: edit): i
Added phpcs:ignore comment to line 1

&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;
[33mERRORS[0m at line 6, column 1:
  Line indented incorrectly; expected at least 4 spaces, found 0
  Sniff: Generic.WhiteSpace.ScopeIndent.Incorrect
  [32m(Auto-fixable)[0m

      [90m  4  class test[0m
      [90m  5  {[0m
      [31m  6- echo &#8216;hello&#8217;;[0m
      [32m  6+     echo &#8216;hello&#8217;;[0m
      [90m  7  }[0m
      [90m  8  [0m
Choose an action:
  [f] Fix automatically
  [i] Add a phpcs:ignore to this line (phpcs:ignore)
  [d] Disable this sniff for this file (phpcs:disable)
  [p] Project-wide: exclude this sniff in phpcs.xml
  [e] Edit the file manually
  [s] Skip this violation
  [q] Quit
Action (default: auto-fix):
Auto-fixing&#8230;
[32mFixed![0m

&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;
[33mERRORS[0m at line 3, column 1:
  No space found before comment text; expected &#8220;// helo&#8221; but found &#8220;//helo&#8221;
  Sniff: Squiz.Commenting.InlineComment.NoSpaceBefore
  [32m(Auto-fixable)[0m

      [90m  1  &lt;?php[0m
      [90m  2  [0m
      [31m  3- //helo[0m
      [32m  3+ // helo[0m
      [90m  4  class test[0m
      [90m  5  {[0m
Choose an action:
  [f] Fix automatically
  [i] Add a phpcs:ignore to this line (phpcs:ignore)
  [d] Disable this sniff for this file (phpcs:disable)
  [p] Project-wide: exclude this sniff in phpcs.xml
  [e] Edit the file manually
  [s] Skip this violation
  [q] Quit
Action (default: auto-fix):
Auto-fixing&#8230;
[32mFixed![0m

&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;
[33mERRORS[0m at line 3, column 1:
  Inline comments must start with a capital letter
  Sniff: Squiz.Commenting.InlineComment.NotCapital
  [36m(Interactive fixes available)[0m

[1mInteractive Fix Options:[0m
  [1] Suggestion
      [90m  1  &lt;?php[0m
      [90m  2  [0m
      [31m  3- // helo[0m
      [32m  3+ // Helo[0m
      [90m  4  class test[0m
      [90m  5  {[0m

Choose an action:
  [1] Apply: Suggestion
  [i] Add a phpcs:ignore to this line (phpcs:ignore)
  [d] Disable this sniff for this file (phpcs:disable)
  [p] Project-wide: exclude this sniff in phpcs.xml
  [e] Edit the file manually
  [s] Skip this violation
  [q] Quit
Action (default: 1 &#8220;Capitalize first letter&#8221;):
Applying option 1&#8230;
[32mFixed![0m

&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;
[33mERRORS[0m at line 3, column 1:
  Inline comments must end in full-stops, exclamation marks, or question marks
  Sniff: Squiz.Commenting.InlineComment.InvalidEndChar
  [36m(Interactive fixes available)[0m

[1mInteractive Fix Options:[0m
  [1] Append a .
      [90m  1  &lt;?php[0m
      [90m  2  [0m
      [31m  3- // Helo[0m
      [32m  3+ // Helo.[0m
      [90m  4  class test[0m
      [90m  5  {[0m
  [2] Append a !
      [90m  1  &lt;?php[0m
      [90m  2  [0m
      [31m  3- // Helo[0m
      [32m  3+ // Helo![0m
      [90m  4  class test[0m
      [90m  5  {[0m
  [3] Append a ?
      [90m  1  &lt;?php[0m
      [90m  2  [0m
      [31m  3- // Helo[0m
      [32m  3+ // Helo?[0m
      [90m  4  class test[0m
      [90m  5  {[0m
  [4] Remove comment
      [90m  1  &lt;?php[0m
      [90m  2  [0m
      [31m  3- // Helo[0m
      [90m  4  class test[0m
      [90m  5  {[0m

Choose an action:
  [1] Apply: Append a .
  [2] Apply: Append a !
  [3] Apply: Append a ?
  [4] Apply: Remove comment
  [i] Add a phpcs:ignore to this line (phpcs:ignore)
  [d] Disable this sniff for this file (phpcs:disable)
  [p] Project-wide: exclude this sniff in phpcs.xml
  [e] Edit the file manually
  [s] Skip this violation
  [q] Quit
Action (default: 1 &#8220;Append a .&#8221;): 2
Fixing with option 2&#8230;
[32mFixed![0m

&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;
[33mERRORS[0m at line 4, column 7:
  Test name must begin with a capital letter
  Sniff: PEAR.NamingConventions.ValidClassName.StartWithCapital
  [36m(Interactive fixes available)[0m

[1mInteractive Fix Options:[0m
  [1] Suggestion
      [90m  2  [0m
      [90m  3  // Helo![0m
      [31m  4- class test[0m
      [32m  4+ class Test[0m
      [90m  5  {[0m
      [90m  6      echo &#8216;hello&#8217;;[0m

Choose an action:
  [1] Apply: Suggestion
  [i] Add a phpcs:ignore to this line (phpcs:ignore)
  [d] Disable this sniff for this file (phpcs:disable)
  [p] Project-wide: exclude this sniff in phpcs.xml
  [e] Edit the file manually
  [s] Skip this violation
  [q] Quit
Action (default: 1 &#8220;Capitalize first letter&#8221;):
Applying option 1&#8230;
[32mFixed![0m

&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;

[1mPHPCBF RESULT SUMMARY[0m
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-
[1mFILE                                                  FIXED  REMAINING[0m
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-
test.php                                              5      0
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-
[1mA TOTAL OF 5 ERRORS WERE FIXED IN 1 FILE[0m
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-

❯ bat test.php
[38;5;246m───────┬────────────────────────────────────────────────────────────────────────[0m
       [38;5;246m│ [0mFile: [1mtest.php[0m
[38;5;246m───────┼────────────────────────────────────────────────────────────────────────[0m
[38;5;246m   1[0m   [38;5;246m│[0m [38;5;231m&lt;?php[0m[38;5;231m [0m[38;5;242m//[0m[38;5;242m phpcs:ignore PEAR.Commenting.FileComment.WrongStyle[0m
[38;5;246m   2[0m   [38;5;246m│[0m 
[38;5;246m   3[0m   [38;5;246m│[0m [38;5;242m//[0m[38;5;242m Helo![0m
[38;5;246m   4[0m   [38;5;246m│[0m [38;5;149mclass[0m[38;5;231m [0m[4;38;5;81mTest[0m
[38;5;246m   5[0m   [38;5;246m│[0m [38;5;231m{[0m
[38;5;246m   6[0m   [38;5;246m│[0m [38;5;231m    [0m[38;5;167mecho[0m[38;5;231m [0m[38;5;186m&#8217;[0m[38;5;186mhello[0m[38;5;186m&#8217;[0m[38;5;231m;[0m
[38;5;246m   7[0m   [38;5;246m│[0m [38;5;231m}[0m
[38;5;246m───────┴────────────────────────────────────────────────────────────────────────[0m

</div>


<p>For comparison, this is what regular mode produces:</p>


<div class="wp-block-syntaxhighlighter-code ">
❯ ./bin/phpcbf test.php

[1mPHPCBF RESULT SUMMARY[0m
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-
[1mFILE                                                  FIXED  REMAINING[0m
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-
test.php                                              2      4
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-
[1mA TOTAL OF 2 ERRORS WERE FIXED IN 1 FILE[0m
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-

❯ bat test.php
[38;5;246m───────┬────────────────────────────────────────────────────────────────────────[0m
       [38;5;246m│ [0mFile: [1mtest.php[0m
[38;5;246m───────┼────────────────────────────────────────────────────────────────────────[0m
[38;5;246m   1[0m   [38;5;246m│[0m [38;5;231m&lt;?php[0m
[38;5;246m   2[0m   [38;5;246m│[0m 
[38;5;246m   3[0m   [38;5;246m│[0m [38;5;242m//[0m[38;5;242m helo[0m
[38;5;246m   4[0m   [38;5;246m│[0m [38;5;149mclass[0m[38;5;231m [0m[4;38;5;81mtest[0m
[38;5;246m   5[0m   [38;5;246m│[0m [38;5;231m{[0m
[38;5;246m   6[0m   [38;5;246m│[0m [38;5;231m    [0m[38;5;167mecho[0m[38;5;231m [0m[38;5;186m&#8217;[0m[38;5;186mhello[0m[38;5;186m&#8217;[0m[38;5;231m;[0m
[38;5;246m   7[0m   [38;5;246m│[0m [38;5;231m}[0m
[38;5;246m───────┴────────────────────────────────────────────────────────────────────────[0m

</div></details>



<p></p>



<p>You can find <a href="https://github.com/PHPCSStandards/PHP_CodeSniffer/issues/1285">the issue I created about this in the PHP CodeSniffer repo</a>, and <a href="https://github.com/PHPCSStandards/PHP_CodeSniffer/compare/4.x...akirk:PHP_CodeSniffer:phpcbf-interactive">my implementation on Github</a>. This is not yet a PR because <a href="https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/4.x/.github/CONTRIBUTING.md#requestingsubmitting-new-features">they prefer to have a discussion it first</a> but I worked on an implementation already so that you can experience how it feels to use it and don&#8217;t just have to imagine it. Find the instructions to do so <a href="https://github.com/PHPCSStandards/PHP_CodeSniffer/issues/1285">on the bottom of the issue</a>.</p>



<p>PS: to make the terminal output look well in this post, I have made this <a href="https://github.com/akirk/syntaxhighlighter-ansi">syntaxhighlighter-ansi</a> plugin for the <a href="https://wordpress.com/plugins/syntaxhighlighter">SyntaxHighlighter Evolved plugin</a> for WordPress that will interpret the ANSI escape sequences from the terminal and convert it to colorful output like you can see above.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://alex.kirk.at/2025/09/29/proposal-an-interactive-mode-for-phpcbf/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<friends:post-format>standard</friends:post-format>
	</item>
		<item>
		<title>npm install playground-step-library</title>
		<link>https://alex.kirk.at/2025/09/05/npm-install-playground-step-library/</link>
					<comments>https://alex.kirk.at/2025/09/05/npm-install-playground-step-library/#comments</comments>
		
		<dc:creator><![CDATA[Alex Kirk]]></dc:creator>
		<pubDate>Fri, 05 Sep 2025 14:14:57 +0000</pubDate>
				<category><![CDATA[Code]]></category>
		<category><![CDATA[Playground]]></category>
		<guid isPermaLink="false">https://alex.kirk.at/?p=2768972</guid>

					<description><![CDATA[I have updated my Playground Step Library (which I had written about before)–the tool that allows you to use more advanced steps in WordPress Playground–so that it can now also be used programmatically: It is now an npm package: playground-step-library. Behind the scenes this actually dominoed into migrating it to TypeScript and restructuring the code [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p>I have updated <a href="https://github.com/akirk/playground-step-library/" data-type="post" data-id="1996330">my Playground Step Library</a> (<a href="https://alex.kirk.at/2024/07/11/wordpress-playground-step-library/" data-type="post" data-id="1996330">which I had written about before</a>)–the tool that allows you to use <a href="https://github.com/akirk/playground-step-library/tree/main/docs">more advanced steps</a> in <a href="https://playground.wordpress.net/">WordPress Playground</a>–so that it can now also be used programmatically: It is now an npm package: <a href="https://www.npmjs.com/package/playground-step-library">playground-step-library</a>.</p>



<p>Behind the scenes this actually <a href="https://github.com/akirk/playground-step-library/pull/5">dominoed into</a> migrating it to TypeScript and restructuring the code so that it now both powers the <a href="https://akirk.github.io/playground-step-library/">Web UI</a> and the npm package.</p>



<p>Having those custom steps available now makes even more sense that the <a href="https://www.npmjs.com/package/@wp-playground/cli">Playground CLI</a> is production ready and you can use it for things like testing your WordPress plugin with Playwright, see this presentation <a href="https://wordpress.tv/2025/06/07/building-automated-tests-with-wordpress-playground/">Building Automated Tests with WordPress Playground</a> from WordCamp Europe 2025 by my colleague <a href="https://github.com/bgrgicak/">Berislav &#8220;Bero&#8221; Grigicak</a>.</p>



<p>In this example you can see a blueprint JSON that contains steps <code>setSiteName</code> and <code>addPage</code> that <a href="https://wordpress.github.io/wordpress-playground/blueprints/steps/#">don&#8217;t exist in the library of steps of Playground</a>. At the time of writing there are <a href="https://github.com/akirk/playground-step-library/tree/main/docs#custom-steps">36 custom steps</a> with the goal of making it easier to do things that can be done with a blueprint already but need some complexity. See in the example below how creating a page can be done with <code>runPHP</code> and <code>wp_insert_post</code> but it&#8217;s visually easier with a step <code>addPage</code>.</p>



<pre class="wp-block-preformatted">import PlaygroundStepLibrary from 'playground-step-library';<br>const compiler = new PlaygroundStepLibrary();<br><br>const blueprint = {<br>    steps: [<br>        {<br>            step: '<mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-pale-pink-color">setSiteName</mark>',<br>            sitename: '<mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-vivid-purple-color">My Site</mark>',<br>            tagline: '<mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-luminous-vivid-orange-color">A WordPress Playground demo</mark>'<br>        },<br>        {<br>            step: '<mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-vivid-cyan-blue-color">addPage</mark>',<br>            title: '<mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-vivid-green-cyan-color">Welcome</mark>',<br>            content: '&lt;p><mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-luminous-vivid-amber-color">Welcome to my site!</mark>&lt;/p>'<br>        }<br>    ]<br>};<br><br>const compiledBlueprint = compiler.compile(blueprint);<br>console.log(compiledBlueprint);</pre>



<p>Which turns this into a valid blueprint:</p>



<pre class="wp-block-preformatted">{<br>  "steps": [<br>    {<br>      "step": "<mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-pale-pink-color">setSiteOptions</mark>",<br>      "options": {<br>        "blogname": "<mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-vivid-purple-color">My Site</mark>",<br>        "blogdescription": "<mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-luminous-vivid-orange-color">A WordPress Playground demo</mark>"<br>      }<br>    },<br>    {<br>      "step": "<mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-vivid-cyan-blue-color">runPHP</mark>",<br>      "code": "\n&lt;?php require_once '/wordpress/wp-load.php';\n$page_args = array(\n\t'post_type'    => 'page',\n\t'post_status'  => 'publish',\n\t'post_title'   => '<mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-vivid-green-cyan-color">Welcome</mark>',\n\t'post_content' => '&lt;p><mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-luminous-vivid-amber-color">Welcome to my site!</mark>&lt;/p>',\n);\n$page_id = <mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-vivid-cyan-blue-color">wp_insert_post</mark>( $page_args );"<br>    }<br>  ]<br>}</pre>



<p>You can then pass this blueprint to playground CLI to run it (<a href="https://github.com/fellyph/playwright-testing-plugin/tree/main/demos">see other demos</a> by my colleague <a href="https://blog.fellyph.com.br/">Fellyph</a>):</p>



<pre class="wp-block-code"><code>import { runCLI, RunCLIServer } from '@wp-playground/cli';
await runCLI({
  command: 'server',
  login: true,
  blueprint: compiledBlueprint
});</code></pre>



<p>You can also <a href="https://playground.wordpress.net/?blueprint-url=data:application/json;base64,eyJzdGVwcyI6W3sic3RlcCI6InNldFNpdGVPcHRpb25zIiwib3B0aW9ucyI6eyJibG9nbmFtZSI6Ik15IFNpdGUiLCJibG9nZGVzY3JpcHRpb24iOiJBIFdvcmRQcmVzcyBzaXRlIn19LHsic3RlcCI6InJ1blBIUCIsImNvZGUiOiI8P3BocCByZXF1aXJlX29uY2UgJy93b3JkcHJlc3Mvd3AtbG9hZC5waHAnO1xuJHBhZ2VfYXJncyA9IGFycmF5KFxuJ3Bvc3RfdHlwZScgICAgPT4gJ3BhZ2UnLFxuJ3Bvc3Rfc3RhdHVzJyAgPT4gJ3B1Ymxpc2gnLFxuJ3Bvc3RfdGl0bGUnICAgPT4gJ1dlbGNvbWUnLFxuJ3Bvc3RfY29udGVudCcgPT4gJzxwPldlbGNvbWUgdG8gbXkgc2l0ZSE8L3A%2BJyxcbik7XG4kcGFnZV9pZCA9IHdwX2luc2VydF9wb3N0KCAkcGFnZV9hcmdzICk7dXBkYXRlX29wdGlvbiggJ3BhZ2Vfb25fZnJvbnQnLCAkcGFnZV9pZCApO3VwZGF0ZV9vcHRpb24oICdzaG93X29uX2Zyb250JywgJ3BhZ2UnICk7In1dfQ%3D%3D">conveniently try it out in WordPress Playground with this link</a> (and also <a href="https://akirk.github.io/playground-step-library/#eyJzdGVwcyI6W3sic3RlcCI6InNldFNpdGVOYW1lIiwidmFycyI6eyJzaXRlbmFtZSI6Ik15IFNpdGUiLCJ0YWdsaW5lIjoiQSBXb3JkUHJlc3Mgc2l0ZSJ9fSx7InN0ZXAiOiJhZGRQYWdlIiwidmFycyI6eyJwb3N0VGl0bGUiOiJXZWxjb21lIiwicG9zdENvbnRlbnQiOiI8cD5XZWxjb21lIHRvIG15IHNpdGUhPC9wPiIsImhvbWVwYWdlIjp0cnVlfX1dfQ==">view in the Step Library UI</a>).</p>



<p>Finally, in the repo there are <a href="https://github.com/akirk/playground-step-library/tree/main/examples">a number of examples</a> that you can browse and I created a little screen recording of a few of them:</p>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="800" height="661" src="https://alex.kirk.at/wp-content/uploads/sites/2/2025/09/playground-step-library-examples.gif" alt="" class="wp-image-2769055"/></figure>



<p>Happy coding!</p>
]]></content:encoded>
					
					<wfw:commentRss>https://alex.kirk.at/2025/09/05/npm-install-playground-step-library/feed/</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		
		<friends:post-format>standard</friends:post-format>
	</item>
		<item>
		<title>Can&#8217;t Follow You!</title>
		<link>https://alex.kirk.at/2025/06/19/cant-follow-you/</link>
					<comments>https://alex.kirk.at/2025/06/19/cant-follow-you/#comments</comments>
		
		<dc:creator><![CDATA[Alex Kirk]]></dc:creator>
		<pubDate>Thu, 19 Jun 2025 05:53:54 +0000</pubDate>
				<category><![CDATA[Fediverse]]></category>
		<category><![CDATA[Web]]></category>
		<guid isPermaLink="false">https://alex.kirk.at/?p=2605214</guid>

					<description><![CDATA[So, I created this little website https://cantfollowyou.kirk.at/ as something that you can send to people who don&#8217;t realize that they are on a closed network and what it means to others. A bit like Let me Google that for you but for the Fediverse. Here is the backstory, and some details around it: I attended [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p>So, I created this little website <a href="https://cantfollowyou.kirk.at/">https://cantfollowyou.kirk.at/</a> as something that you can send to people who don&#8217;t realize that they are on a closed network and what it means to others. A bit like <a href="https://letmegooglethat.com/">Let me Google that for you</a> but for the Fediverse. Here is the backstory, and some details around it:</p>



<p>I attended (German-spoken) <a href="https://graz.fedi.camp/">FediCamp Graz 2025</a> last Saturday (see <a href="https://wittenbrink.net/das-erste-grazer-fedicamp/">Heinz Wittenbrink&#8217;s summary in German</a>) where we discussed a plethora of topics around the Fediverse, barcamp-style.</p>



<p>One question that we discussed and that has been bugging me for a long time, is why people are quite unwilling to switch to federated, open networks.</p>



<p>One reason is certainly is inertia. I guess it&#8217;s a human property to stick with what you know. Also change means work.</p>



<p>Another reason is ignorance. You know, like &#8220;bliss.&#8221; It can be comforting to focus on the <a href="https://alex.kirk.at/2025/04/24/wordpress-as-a-refuge-from-algorithms/" data-type="post" data-id="2491886">good sides of your social consumption and not deal too much with the negative sides</a>.</p>



<p>Following a train of thought, I realized that maybe many people don&#8217;t realize that they can&#8217;t be followed by people who are not on their network. And don&#8217;t realize that this is a lock-in by the platform that is not necessary.</p>



<p>To combat this, I created a <a href="https://cantfollowyou.kirk.at/">little one-page website</a> (<a href="https://github.com/akirk/cantfollowyou">source on Github</a>, open to PRs!) that is meant as something that you can take and send this URL to a person you&#8217;d like to follow who is on a closed social network.</p>



<figure class="wp-block-image size-large"><a href="https://cantfollowyou.kirk.at/insta/Alex"><img loading="lazy" decoding="async" width="1024" height="816" src="https://alex.kirk.at/wp-content/uploads/sites/2/2025/06/cantfollowyou-1-1024x816.png" alt="" class="wp-image-2605220" srcset="https://alex.kirk.at/wp-content/uploads/sites/2/2025/06/cantfollowyou-1-1024x816.png 1024w, https://alex.kirk.at/wp-content/uploads/sites/2/2025/06/cantfollowyou-1-655x522.png 655w, https://alex.kirk.at/wp-content/uploads/sites/2/2025/06/cantfollowyou-1-768x612.png 768w, https://alex.kirk.at/wp-content/uploads/sites/2/2025/06/cantfollowyou-1-1536x1225.png 1536w, https://alex.kirk.at/wp-content/uploads/sites/2/2025/06/cantfollowyou-1.png 1598w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a><figcaption class="wp-element-caption">A personalized URL <a href="https://cantfollowyou.kirk.at/insta/Alex">https://cantfollowyou.kirk.at/insta/Alex</a> shows the closed network and it&#8217;s alternative</figcaption></figure>



<p>It contains a table of ActivityPub equivalents of social networks (see also my WordCamp Europe 2025 presentation <a href="https://europe.wordcamp.org/2025/session/what-youre-missing-if-you-dont-have-your-own-wordpress/">What you’re missing if you don’t have your own WordPress</a>; <a href="https://alex.kirk.at/wceu2025/" data-type="page" data-id="2551153">slides</a>, <a href="https://wordpress.tv/2025/06/07/what-youre-missing-if-you-dont-have-your-own-wordpress/">video</a>):</p>



<figure class="wp-block-image size-large"><a href="https://cantfollowyou.kirk.at/"><img loading="lazy" decoding="async" width="806" height="1024" src="https://alex.kirk.at/wp-content/uploads/sites/2/2025/06/cantfollowyou-table-806x1024.png" alt="" class="wp-image-2605221" srcset="https://alex.kirk.at/wp-content/uploads/sites/2/2025/06/cantfollowyou-table-806x1024.png 806w, https://alex.kirk.at/wp-content/uploads/sites/2/2025/06/cantfollowyou-table-630x800.png 630w, https://alex.kirk.at/wp-content/uploads/sites/2/2025/06/cantfollowyou-table-768x976.png 768w, https://alex.kirk.at/wp-content/uploads/sites/2/2025/06/cantfollowyou-table-1209x1536.png 1209w, https://alex.kirk.at/wp-content/uploads/sites/2/2025/06/cantfollowyou-table.png 1420w" sizes="auto, (max-width: 806px) 100vw, 806px" /></a></figure>



<p>At the bottom of the page you can customize it:</p>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="679" height="55" src="https://alex.kirk.at/wp-content/uploads/sites/2/2025/06/cantfollowyou-enter.gif" alt="" class="wp-image-2605222"/></figure>



<p>Probably this is not going to change the needle significantly, but I see this as a little contribution to enable raising awareness about the problem. The decentralized fediverse surely has a steeper learning curve because you need to make a choice before you start. But I think it&#8217;s worth it.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://alex.kirk.at/2025/06/19/cant-follow-you/feed/</wfw:commentRss>
			<slash:comments>6</slash:comments>
		
		
		<friends:post-format>standard</friends:post-format>
	</item>
		<item>
		<title></title>
		<link>https://alex.kirk.at/2025/04/26/2499219/</link>
					<comments>https://alex.kirk.at/2025/04/26/2499219/#respond</comments>
		
		<dc:creator><![CDATA[Alex Kirk]]></dc:creator>
		<pubDate>Sat, 26 Apr 2025 09:41:37 +0000</pubDate>
				<category><![CDATA[Web]]></category>
		<category><![CDATA[WCVIE]]></category>
		<guid isPermaLink="false">https://alex.kirk.at/2025/04/26/2499219/</guid>

					<description><![CDATA[Folien meiner #wcvie Präsentation: https://alex.kirk.at/wcvie-2025]]></description>
										<content:encoded><![CDATA[<p>Folien meiner <a rel="tag" class="hashtag u-tag u-category" href="/friends/tag/wcvie/">#wcvie</a> Präsentation: <a href="https://alex.kirk.at/wcvie-2025">https://alex.kirk.at/wcvie-2025</a></p><p><!-- /wp:post-content --><!-- wp:activitypub/reactions /--></p>]]></content:encoded>
					
					<wfw:commentRss>https://alex.kirk.at/2025/04/26/2499219/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<friends:post-format>status</friends:post-format>
	</item>
		<item>
		<title></title>
		<link>https://alex.kirk.at/2025/04/26/2499105/</link>
					<comments>https://alex.kirk.at/2025/04/26/2499105/#respond</comments>
		
		<dc:creator><![CDATA[Alex Kirk]]></dc:creator>
		<pubDate>Sat, 26 Apr 2025 08:00:07 +0000</pubDate>
				<category><![CDATA[Web]]></category>
		<category><![CDATA[WCVIE]]></category>
		<guid isPermaLink="false">https://alex.kirk.at/2025/04/26/2499105/</guid>

					<description><![CDATA[Starting my talk at #wcvie now! https://vienna.wordcamp.org/2025/session/dein-wordpress-kann-viel-mehr-als-du-glaubst/]]></description>
										<content:encoded><![CDATA[<p>Starting my talk at <a rel="tag" class="hashtag u-tag u-category" href="/friends/tag/wcvie/">#wcvie</a> now! <a href="https://vienna.wordcamp.org/2025/session/dein-wordpress-kann-viel-mehr-als-du-glaubst/" rel="nofollow">https://vienna.wordcamp.org/2025/session/dein-wordpress-kann-viel-mehr-als-du-glaubst/</a></p><p></p><!-- /wp:post-content -->]]></content:encoded>
					
					<wfw:commentRss>https://alex.kirk.at/2025/04/26/2499105/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<friends:post-format>status</friends:post-format>
	</item>
		<item>
		<title>WordPress as a Refuge from Algorithms</title>
		<link>https://alex.kirk.at/2025/04/24/wordpress-as-a-refuge-from-algorithms/</link>
					<comments>https://alex.kirk.at/2025/04/24/wordpress-as-a-refuge-from-algorithms/#comments</comments>
		
		<dc:creator><![CDATA[Alex Kirk]]></dc:creator>
		<pubDate>Thu, 24 Apr 2025 07:32:40 +0000</pubDate>
				<category><![CDATA[Enable Mastodon Apps]]></category>
		<category><![CDATA[Friends Plugin]]></category>
		<category><![CDATA[Playground]]></category>
		<category><![CDATA[Web]]></category>
		<category><![CDATA[WordPress]]></category>
		<guid isPermaLink="false">https://alex.kirk.at/?p=2491886</guid>

					<description><![CDATA[In a previous post, I have written about how you can use WordPress as your own Mastodon instance with the three plugins ActivityPub, Friends, and Enable Mastodon Apps. The Friends plugin also provides an RSS/Atom feed parser (and can be extended with more of them) so you that you can automatically receive content from many [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p>In a previous post, I have written about how you can use <a href="https://alex.kirk.at/2024/06/13/your-wordpress-as-your-personal-mastodon-instance/" data-type="post" data-id="1996331">WordPress as your own Mastodon instance</a> with the three plugins <a href="https://wordpress.org/plugins/activitypub">ActivityPub</a>, <a href="https://friends.kirk.at">Friends</a>, and <a href="https://ema.kirk.at">Enable Mastodon Apps</a>.</p>



<p>The Friends plugin also provides an RSS/Atom feed parser (and can be extended with more of them) so you that you can automatically receive content from many sources. You can also save posts from around the web using the <a href="https://github.com/akirk/friends-post-collection">Post Collection plugin</a>, which also provides a &#8220;retrieve full content&#8221; for excerpt-only RSS feeds. To read what you&#8217;ve saved without distractions, you can then <a href="https://github.com/akirk/friends-send-to-e-reader">send this to your e-reader</a>.</p>



<p>Because this runs on your WordPress, it means that <strong>you don&#8217;t have to play by the rules set by others</strong> (= the social media platform that hosts you). I am not talking about illegal content or anything similar, but rather avoiding exposure to unsolicited content that is intended solely to keep you addicted to the platform.</p>



<p>Another aspect for which I believe WordPress is excellent is maintaining private blogs for content that you don&#8217;t want to put on the public web, such as photos of your children. Or a <a href="https://alex.kirk.at/2024/01/19/keeping-a-family-wiki/" data-type="post" data-id="1919057">family wiki</a>, a Wikipedia for your family members. All these are things that I prefer not to expose to algorithms like those used by social media platforms.</p>



<h3 class="wp-block-heading">Digital Consumption Pyramid, modeled after the <a href="https://en.wikipedia.org/wiki/Food_pyramid_(nutrition)">Food Pyramid</a></h3>



<p>For our digital consumption, I propose we model this after the food pyramid. Sweets (= the addictive stuff) is on the top, it is ok to consume some, but it should not dominate. Below that, we&#8217;d have video games, then time on productive systems without algorithms like your own WordPress, or messaging with your friends. I believe the base should consist of research and reading for gaining knowledge. </p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="455" src="https://alex.kirk.at/wp-content/uploads/sites/2/2025/04/digital-consumption-pyramid-1024x455.png" alt="" class="wp-image-2494917" srcset="https://alex.kirk.at/wp-content/uploads/sites/2/2025/04/digital-consumption-pyramid-1024x455.png 1024w, https://alex.kirk.at/wp-content/uploads/sites/2/2025/04/digital-consumption-pyramid-655x291.png 655w, https://alex.kirk.at/wp-content/uploads/sites/2/2025/04/digital-consumption-pyramid-768x341.png 768w, https://alex.kirk.at/wp-content/uploads/sites/2/2025/04/digital-consumption-pyramid-1536x682.png 1536w, https://alex.kirk.at/wp-content/uploads/sites/2/2025/04/digital-consumption-pyramid-2048x910.png 2048w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<p>This is just my own suggestion that I may need to adjust over time. However, I think it illustrates the point that you should be conscious of your own digital and screen time: Your WordPress can be a place for your own consumption needs, away from algorithms that try to manipulate you.</p>



<p>Yes, it&#8217;s harder to set up a WordPress than just creating a social media account. I believe that with <a href="https://akirk.github.io/playground-step-library/">Playground and blueprints</a> this will become easier soon. But this little bit of extra work gives you the freedom to not be constantly monitored in order to manipulate you with new content to stay on the platform. Or have your data be used for training AI.</p>



<p>I&#8217;ll be talking about the above in more detail this weekend <a href="https://vienna.wordcamp.org/2025/session/dein-wordpress-kann-viel-mehr-als-du-glaubst/">in German at WordCamp Vienna (April 25, 2025 at 10am)</a>, and <a href="https://europe.wordcamp.org/2025/session/your-wordpress-can-do-so-much-more-than-you-think/">in English at WordCamp Europe (June 7, 2025 at 2pm) in Basel, Switzerland</a>. See you there!</p>
]]></content:encoded>
					
					<wfw:commentRss>https://alex.kirk.at/2025/04/24/wordpress-as-a-refuge-from-algorithms/feed/</wfw:commentRss>
			<slash:comments>4</slash:comments>
		
		
		<friends:post-format>standard</friends:post-format>
	</item>
	</channel>
</rss>
