<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Blogs on Kristoffer.dev</title><link>https://kristoffer.dev/~/writing/</link><description>Recent content in Blogs on Kristoffer.dev</description><generator>Hugo -- 0.160.1</generator><language>en</language><lastBuildDate>Wed, 30 Sep 2026 06:30:00 +0200</lastBuildDate><atom:link href="https://kristoffer.dev/~/writing/index.xml" rel="self" type="application/rss+xml"/><item><title>The macOS Apps I Actually Keep</title><link>https://kristoffer.dev/~/writing/must-have-macos-apps/</link><pubDate>Wed, 30 Sep 2026 06:30:00 +0200</pubDate><guid>https://kristoffer.dev/~/writing/must-have-macos-apps/</guid><description>Itsycal, Rectangle, Obsidian, Raycast and Stats. Five apps that stay on every Mac I use.</description></item><item><title>A Claude Code Status Line That Tells Me When I'll Run Out</title><link>https://kristoffer.dev/~/writing/claude-code-status-line/</link><pubDate>Sun, 27 Sep 2026 11:00:00 +0200</pubDate><guid>https://kristoffer.dev/~/writing/claude-code-status-line/</guid><description>My Claude Code status line is now a small dashboard: weather from my own CLI, rate limits that know my pace, and a bill that is right. Bash and jq, about 50 ms a refresh.</description></item><item><title>Installing Oh My Zsh on Linux and macOS</title><link>https://kristoffer.dev/~/writing/oh-my-szh/</link><pubDate>Wed, 08 Jul 2026 10:00:00 +0200</pubDate><guid>https://kristoffer.dev/~/writing/oh-my-szh/</guid><description>A up-to-date, copy-paste guide to installing and configuring Zsh + Oh My Zsh on Linux (Ubuntu/Debian) and macOS — with themes, must-have plugins, and Nerd Fonts.</description></item><item><title>CLI-first AI Agents: Why I Build Small Tools Instead of MCP Servers</title><link>https://kristoffer.dev/~/writing/cli-over-mcp/</link><pubDate>Fri, 15 May 2026 10:00:00 +0200</pubDate><guid>https://kristoffer.dev/~/writing/cli-over-mcp/</guid><description>How I build small, isolated CLI tools in Go for AI agents to operate in — and why I prefer this over MCP.</description></item><item><title>Building a Hardened Linux Environment for Your OpenClaw AI Agent</title><link>https://kristoffer.dev/~/writing/hardened-linux-environment-for-openclaw-ai-agent/</link><pubDate>Thu, 05 Feb 2026 09:00:00 +0100</pubDate><guid>https://kristoffer.dev/~/writing/hardened-linux-environment-for-openclaw-ai-agent/</guid><description>&lt;blockquote&gt;
&lt;p&gt;A practical, opinionated guide to running an autonomous AI assistant on a dedicated home lab server — with proper isolation, network control, and custom tooling.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id="goals"&gt;Goals&lt;/h2&gt;
&lt;p&gt;You want a dedicated, always-on Linux machine that runs an AI agent (OpenClaw) with the following properties:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Isolated execution environment&lt;/strong&gt; — The agent runs under a dedicated Linux user (&lt;code&gt;agent-openclaw&lt;/code&gt;) with strict permission boundaries. It cannot escalate to root, cannot access other users&amp;rsquo; data, and operates within well-defined filesystem and process boundaries.&lt;/p&gt;</description></item><item><title>Creating Your First Homebrew Tap: A Complete Guide</title><link>https://kristoffer.dev/~/writing/guide-to-creating-your-first-homebrew-tap/</link><pubDate>Wed, 07 Jan 2026 09:00:00 +0100</pubDate><guid>https://kristoffer.dev/~/writing/guide-to-creating-your-first-homebrew-tap/</guid><description>Learn how to create and publish your own Homebrew tap to distribute your CLI tools and applications to macOS and Linux users.</description></item><item><title>Spark from NDC Oslo: Events as Internal APIs</title><link>https://kristoffer.dev/~/writing/sparks-from-ndc-events-as-apis/</link><pubDate>Wed, 28 May 2025 09:00:00 +0200</pubDate><guid>https://kristoffer.dev/~/writing/sparks-from-ndc-events-as-apis/</guid><description>A spark of insight from James Eastham&amp;#39;s NDC Oslo talk: Treat your events like internal APIs.</description></item><item><title>Link Sparks: The Power of Ten - Rules for Developing Safety Critical Code</title><link>https://kristoffer.dev/~/writing/power-of-ten/</link><pubDate>Sat, 05 Apr 2025 09:00:00 +0200</pubDate><guid>https://kristoffer.dev/~/writing/power-of-ten/</guid><description>NASA&amp;#39;s ten rules for safety-critical code, and ThePrimeagen reading them out loud. Simple control flow, bounded loops, no surprises.</description></item><item><title>Obsidian + GitHub: Safe .gitignore Setup</title><link>https://kristoffer.dev/~/writing/obsidian-gitignore/</link><pubDate>Sat, 04 Jan 2025 09:00:00 +0100</pubDate><guid>https://kristoffer.dev/~/writing/obsidian-gitignore/</guid><description>&lt;p&gt;Syncing Obsidian vaults with Git works great until machine-specific files create conflicts or you accidentally commit sensitive notes. This guide gives you two battle-tested .gitignore configurations and a safety checklist to avoid common pitfalls.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Quick take&lt;/strong&gt;: Use the Strict setup to eliminate config conflicts entirely. Add .gitattributes for cleaner diffs. Keep your repo private unless you&amp;rsquo;re building a public knowledge base.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="recommended-gitignore"&gt;Recommended &lt;code&gt;.gitignore&lt;/code&gt;&lt;/h2&gt;
&lt;h3 id="a-minimal-keep-plugin-settings-drop-noise"&gt;A) Minimal (Keep plugin settings, drop noise)&lt;/h3&gt;
&lt;p&gt;Keeps plugin settings and config across devices. Excludes cache and workspace files.&lt;/p&gt;</description></item><item><title>Managing Git Submodules: A Quick Guide</title><link>https://kristoffer.dev/~/writing/git_submodule_guide/</link><pubDate>Fri, 03 Jan 2025 09:00:00 +0100</pubDate><guid>https://kristoffer.dev/~/writing/git_submodule_guide/</guid><description>Learn how to set up, update, and manage Git submodules efficiently, with practical examples for developers.</description></item><item><title>Getting Started with Neovim: From Install to LazyVim</title><link>https://kristoffer.dev/~/writing/getting-started-with-neovim-installation-guide/</link><pubDate>Wed, 25 Dec 2024 09:00:00 +0100</pubDate><guid>https://kristoffer.dev/~/writing/getting-started-with-neovim-installation-guide/</guid><description>Neovim on a new machine, the way I actually set it up: one command for the install, LazyVim for the config, twenty keys to survive the first week — and a practice lap you can run on this page.</description></item><item><title>Link Sparks: Essential Knowledge for Programmers</title><link>https://kristoffer.dev/~/writing/link-sparks---essential-knowledge-for-programmers/</link><pubDate>Thu, 28 Nov 2024 09:00:00 +0100</pubDate><guid>https://kristoffer.dev/~/writing/link-sparks---essential-knowledge-for-programmers/</guid><description>A curated GitHub list of the things every programmer should know — algorithms, memory, security and clean code, in one place.</description></item><item><title>Getting Started with Python Environments</title><link>https://kristoffer.dev/~/writing/getting-started-with-python-environments/</link><pubDate>Fri, 22 Nov 2024 08:00:00 +0200</pubDate><guid>https://kristoffer.dev/~/writing/getting-started-with-python-environments/</guid><description>&lt;h1 id="getting-started-with-python-environments-conda-venv-and-installing-dependencies"&gt;Getting Started with Python Environments: Conda, venv, and Installing Dependencies&lt;/h1&gt;
&lt;p&gt;Managing Python projects efficiently requires a solid understanding of virtual environments and dependency management. This guide introduces you to two popular tools—&lt;code&gt;conda&lt;/code&gt; and &lt;code&gt;venv&lt;/code&gt;—and shows you how to set up a project and install dependencies from a &lt;code&gt;requirements.txt&lt;/code&gt; file.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="why-use-virtual-environments"&gt;&lt;strong&gt;Why Use Virtual Environments?&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;Virtual environments allow you to:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Isolate dependencies for each project.&lt;/li&gt;
&lt;li&gt;Avoid conflicts between package versions.&lt;/li&gt;
&lt;li&gt;Maintain a clean global Python installation.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Both &lt;code&gt;conda&lt;/code&gt; and Python&amp;rsquo;s built-in &lt;code&gt;venv&lt;/code&gt; module are excellent tools for creating virtual environments.&lt;/p&gt;</description></item><item><title>How to Check and Clean Up Disk Space on Linux Servers (Ubuntu)</title><link>https://kristoffer.dev/~/writing/how-to-check-and-clean-up-disk-space/</link><pubDate>Mon, 02 Sep 2024 08:00:00 +0200</pubDate><guid>https://kristoffer.dev/~/writing/how-to-check-and-clean-up-disk-space/</guid><description>&lt;p&gt;Running out of disk space on your Ubuntu server can cause performance issues and prevent applications from running properly. This guide provides straightforward steps to help you check disk space usage and clean up your server effectively.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Check Current Disk Space Usage&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;To see how much disk space is currently being used, open your terminal and run:&lt;/p&gt;
&lt;div class="code-block" data-lang="bash"&gt;
&lt;div class="code-block-bar"&gt;
&lt;span class="code-block-title"&gt;bash&lt;/span&gt;
&lt;span class="code-block-actions"&gt;&lt;button type="button" class="code-block-btn code-block-copy" data-code-copy aria-label="Copy bash to the clipboard"&gt;Copy&lt;/button&gt;
&lt;/span&gt;
&lt;/div&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;df -h&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;df displays disk space usage.&lt;/li&gt;
&lt;li&gt;-h makes the output human-readable.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This command shows disk usage for all mounted filesystems. Look at the Use% column to identify filesystems with high usage.&lt;/p&gt;</description></item><item><title>How to Resize a Filesystem on Hetzner Cloud VM</title><link>https://kristoffer.dev/~/writing/resize-filesystem-hetzner/</link><pubDate>Wed, 24 Apr 2024 16:43:35 +0100</pubDate><guid>https://kristoffer.dev/~/writing/resize-filesystem-hetzner/</guid><description>&lt;p&gt;If you&amp;rsquo;ve recently upgraded the disk size of a volume on Hetzner Cloud, you&amp;rsquo;ll find that the additional space is not automatically available for use. This is because the filesystem on the disk needs to be resized to utilize the new space. Here’s a straightforward guide on how to resize your filesystem on a Hetzner Cloud virtual machine (VM).&lt;/p&gt;</description></item><item><title>Link Up Your Life: Symlinks in Linux and Windows</title><link>https://kristoffer.dev/~/writing/symbolic-link/</link><pubDate>Mon, 25 Mar 2024 07:48:44 +0200</pubDate><guid>https://kristoffer.dev/~/writing/symbolic-link/</guid><description>&lt;p&gt;Symlinks (symbolic links) are like the ultimate shortcuts in the world of operating systems. They help you point to files and folders from multiple locations without creating duplicates. Let&amp;rsquo;s dive into how you can create and manage symlinks, making your life easier whether you&amp;rsquo;re navigating the Linux terminal or the Windows Command Prompt.&lt;/p&gt;
&lt;h2 id="linux-creating-and-managing-symlinks"&gt;Linux: Creating and Managing Symlinks&lt;/h2&gt;
&lt;h3 id="making-a-symlink"&gt;Making a Symlink&lt;/h3&gt;
&lt;p&gt;In Linux, creating a symlink is as simple as striking a few keys:&lt;/p&gt;</description></item><item><title>Add Private SSH Key(s)</title><link>https://kristoffer.dev/~/writing/setup-ssh-keys/</link><pubDate>Sun, 12 Apr 2020 13:37:36 +0200</pubDate><guid>https://kristoffer.dev/~/writing/setup-ssh-keys/</guid><description>&lt;h1 id="setting-up-ssh-keys-on-a-new-installation"&gt;Setting Up SSH Keys on a New Installation&lt;/h1&gt;
&lt;p&gt;New installations often require setting up SSH keys. Here’s a quick guide on how I configured my new computer with existing SSH keys that were already generated and installed on a remote server.&lt;/p&gt;
&lt;h2 id="step-1-copy-the-private-key"&gt;Step 1: Copy the Private Key&lt;/h2&gt;
&lt;p&gt;First, navigate to the SSH directory:&lt;/p&gt;
&lt;div class="code-block" data-lang="bash"&gt;
&lt;div class="code-block-bar"&gt;
&lt;span class="code-block-title"&gt;bash&lt;/span&gt;
&lt;span class="code-block-actions"&gt;&lt;button type="button" class="code-block-btn code-block-copy" data-code-copy aria-label="Copy bash to the clipboard"&gt;Copy&lt;/button&gt;
&lt;/span&gt;
&lt;/div&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; ~/.ssh/&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;&lt;h2 id="step-2-set-the-correct-access-privileges"&gt;Step 2: Set the Correct Access Privileges&lt;/h2&gt;
&lt;p&gt;It’s important to set the correct read and write permissions for your private key:&lt;/p&gt;</description></item><item><title>Basic git commands</title><link>https://kristoffer.dev/~/writing/basic-git-commands/</link><pubDate>Sat, 31 Aug 2019 19:56:36 +0200</pubDate><guid>https://kristoffer.dev/~/writing/basic-git-commands/</guid><description>&lt;h2 id="hey"&gt;Hey&lt;/h2&gt;
&lt;p&gt;Here&amp;rsquo;s just a simple cheatsheet for the most basic git commands.&lt;/p&gt;
&lt;h3 id="git-init"&gt;git init&lt;/h3&gt;
&lt;div class="gist-embed"&gt;
&lt;script src="https://gist.github.com/KristofferRisa/97e17b38a0cace8d6b26edeb10dc279e.js?file=git-init.sh"&gt;&lt;/script&gt;
&lt;noscript&gt;
&lt;a href="https://gist.github.com/KristofferRisa/97e17b38a0cace8d6b26edeb10dc279e" target="_blank" rel="noopener noreferrer"&gt;
View gist on GitHub: git-init.sh
&lt;/a&gt;
&lt;/noscript&gt;
&lt;/div&gt;
&lt;h3 id="git-add-filefiles"&gt;git add file/files&lt;/h3&gt;
&lt;div class="gist-embed"&gt;
&lt;script src="https://gist.github.com/KristofferRisa/97e17b38a0cace8d6b26edeb10dc279e.js?file=git-add.sh"&gt;&lt;/script&gt;
&lt;noscript&gt;
&lt;a href="https://gist.github.com/KristofferRisa/97e17b38a0cace8d6b26edeb10dc279e" target="_blank" rel="noopener noreferrer"&gt;
View gist on GitHub: git-add.sh
&lt;/a&gt;
&lt;/noscript&gt;
&lt;/div&gt;
&lt;h3 id="git-status"&gt;git status&lt;/h3&gt;
&lt;div class="gist-embed"&gt;
&lt;script src="https://gist.github.com/KristofferRisa/97e17b38a0cace8d6b26edeb10dc279e.js?file=git-status.sh"&gt;&lt;/script&gt;
&lt;noscript&gt;
&lt;a href="https://gist.github.com/KristofferRisa/97e17b38a0cace8d6b26edeb10dc279e" target="_blank" rel="noopener noreferrer"&gt;
View gist on GitHub: git-status.sh
&lt;/a&gt;
&lt;/noscript&gt;
&lt;/div&gt;
&lt;h3 id="git-commit"&gt;git commit&lt;/h3&gt;
&lt;div class="gist-embed"&gt;
&lt;script src="https://gist.github.com/KristofferRisa/97e17b38a0cace8d6b26edeb10dc279e.js?file=git-commit.sh"&gt;&lt;/script&gt;
&lt;noscript&gt;
&lt;a href="https://gist.github.com/KristofferRisa/97e17b38a0cace8d6b26edeb10dc279e" target="_blank" rel="noopener noreferrer"&gt;
View gist on GitHub: git-commit.sh
&lt;/a&gt;
&lt;/noscript&gt;
&lt;/div&gt;
&lt;h3 id="git-push"&gt;git push&lt;/h3&gt;
&lt;div class="gist-embed"&gt;
&lt;script src="https://gist.github.com/KristofferRisa/97e17b38a0cace8d6b26edeb10dc279e.js?file=git-push.sh"&gt;&lt;/script&gt;
&lt;noscript&gt;
&lt;a href="https://gist.github.com/KristofferRisa/97e17b38a0cace8d6b26edeb10dc279e" target="_blank" rel="noopener noreferrer"&gt;
View gist on GitHub: git-push.sh
&lt;/a&gt;
&lt;/noscript&gt;
&lt;/div&gt;
&lt;h3 id="git-pull"&gt;git pull&lt;/h3&gt;
&lt;div class="gist-embed"&gt;
&lt;script src="https://gist.github.com/KristofferRisa/97e17b38a0cace8d6b26edeb10dc279e.js?file=git-pull.sh"&gt;&lt;/script&gt;
&lt;noscript&gt;
&lt;a href="https://gist.github.com/KristofferRisa/97e17b38a0cace8d6b26edeb10dc279e" target="_blank" rel="noopener noreferrer"&gt;
View gist on GitHub: git-pull.sh
&lt;/a&gt;
&lt;/noscript&gt;
&lt;/div&gt;
&lt;h3 id="git-clone"&gt;git clone&lt;/h3&gt;
&lt;div class="gist-embed"&gt;
&lt;script src="https://gist.github.com/KristofferRisa/97e17b38a0cace8d6b26edeb10dc279e.js?file=git-clone.sh"&gt;&lt;/script&gt;
&lt;noscript&gt;
&lt;a href="https://gist.github.com/KristofferRisa/97e17b38a0cace8d6b26edeb10dc279e" target="_blank" rel="noopener noreferrer"&gt;
View gist on GitHub: git-clone.sh
&lt;/a&gt;
&lt;/noscript&gt;
&lt;/div&gt;
&lt;h3 id="git-branch"&gt;git branch&lt;/h3&gt;
&lt;div class="gist-embed"&gt;
&lt;script src="https://gist.github.com/KristofferRisa/97e17b38a0cace8d6b26edeb10dc279e.js?file=git-branch.sh"&gt;&lt;/script&gt;
&lt;noscript&gt;
&lt;a href="https://gist.github.com/KristofferRisa/97e17b38a0cace8d6b26edeb10dc279e" target="_blank" rel="noopener noreferrer"&gt;
View gist on GitHub: git-branch.sh
&lt;/a&gt;
&lt;/noscript&gt;
&lt;/div&gt;
&lt;p&gt;&lt;a href="https://github.github.com/training-kit/downloads/github-git-cheat-sheet.pdf"&gt;https://github.github.com/training-kit/downloads/github-git-cheat-sheet.pdf&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Linux Commands</title><link>https://kristoffer.dev/~/writing/linux-commands/</link><pubDate>Fri, 20 Oct 2017 17:48:44 +0200</pubDate><guid>https://kristoffer.dev/~/writing/linux-commands/</guid><description>&lt;p&gt;Here are some common Linux commands:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;ls&lt;/strong&gt; - used to list the contents of a directory&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;cd&lt;/strong&gt; - used to change the current working directory&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;mv&lt;/strong&gt; - used to move or rename files and directories&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;mkdir&lt;/strong&gt; - used to create a new directory&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;rm&lt;/strong&gt; - used to delete files and directories&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;chmod&lt;/strong&gt; - used to change the permissions of a file or directory&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;sudo&lt;/strong&gt; - used to execute a command with superuser privileges&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;apt-get&lt;/strong&gt; - used to install and manage software packages on Linux systems&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;grep&lt;/strong&gt; - used to search for text patterns in files&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;man&lt;/strong&gt; - used to display the manual pages for a command&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;These are just a few examples - there are many more Linux commands that can be used for various tasks.&lt;/p&gt;</description></item></channel></rss>