<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>Hasse Ramlev Wilson</title>
  <subtitle>Drupal · Symfony · PHP developer</subtitle>
  <link href="https://notes.ramlev.com/feed.xml" rel="self"/>
  <link href="https://notes.ramlev.com/"/>
  <updated>2026-05-04T00:00:00Z</updated>
  <id>https://notes.ramlev.com/</id>
  <author>
    <name>Hasse Ramlev Wilson</name>
    <email>hasse@ramlev.com</email>
  </author>
  
  <entry>
    <title>ZSH Commit message generator</title>
    <link href="https://notes.ramlev.com/posts/zsh-commit-message-generator/"/>
    <id>https://notes.ramlev.com/posts/zsh-commit-message-generator/</id>
    <updated>2026-05-04T00:00:00Z</updated>
    <summary>A zsh function that reads your staged diff and uses Claude to suggest a commit message, with Gum for a nicer terminal UI.</summary>
    <content type="html">&lt;p&gt;One of the main things i use AI (Claude) for is for shellscripts.&lt;/p&gt;
&lt;p&gt;One of the most tedious tasks is to write git commit messages. So i wrote a little zsh function i can use within a git repository, that reads all the changes and suggest to you, a commit message. The script make use of &lt;a href=&quot;https://github.com/charmbracelet/gum&quot;&gt;Gum&lt;/a&gt; to make it all a bit more glamorous.&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function-name function&quot;&gt;commit&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token assign-left variable&quot;&gt;commitMessage&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;$*&lt;/span&gt;&quot;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; gum confirm &lt;span class=&quot;token string&quot;&gt;&quot;Execute git add . ?&quot;&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;--default&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;No&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;then&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;add&lt;/span&gt; &lt;span class=&quot;token builtin class-name&quot;&gt;.&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt;
    &lt;span class=&quot;token assign-left variable&quot;&gt;selected&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;&lt;span class=&quot;token variable&quot;&gt;$(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;diff&lt;/span&gt; --name-only&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; ls-files &lt;span class=&quot;token parameter variable&quot;&gt;--others&lt;/span&gt; --exclude-standard&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;sort&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-u&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; gum choose --no-limit &lt;span class=&quot;token parameter variable&quot;&gt;--header&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Select files to stage:&quot;&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-n&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;$selected&lt;/span&gt;&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;then&lt;/span&gt;
      &lt;span class=&quot;token builtin class-name&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;$selected&lt;/span&gt;&quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;xargs&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;add&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;fi&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;fi&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;diff&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;--cached&lt;/span&gt; --quiet&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;then&lt;/span&gt;
    gum style &lt;span class=&quot;token parameter variable&quot;&gt;--foreground&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;196&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Nothing staged. Aborting.&quot;&lt;/span&gt;
    &lt;span class=&quot;token builtin class-name&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;fi&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;$commitMessage&lt;/span&gt;&quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;then&lt;/span&gt;
    gum style &lt;span class=&quot;token parameter variable&quot;&gt;--border&lt;/span&gt; rounded &lt;span class=&quot;token parameter variable&quot;&gt;--padding&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;1 2&quot;&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;--margin&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;1 0&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;&#92;&lt;/span&gt;
      &lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;&lt;span class=&quot;token variable&quot;&gt;$(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;diff&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;--cached&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;--stat&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&quot;&lt;/span&gt;

    &lt;span class=&quot;token assign-left variable&quot;&gt;diff_input&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;&lt;span class=&quot;token variable&quot;&gt;$(&lt;/span&gt;&lt;span class=&quot;token builtin class-name&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;=== Summary ===&quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;diff&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;--cached&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;--stat&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;&#92;&lt;/span&gt;
                 &lt;span class=&quot;token builtin class-name&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-e&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token entity&quot; title=&quot;&#92;n&quot;&gt;&#92;n&lt;/span&gt;=== Diff (truncated if large) ===&quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;&#92;&lt;/span&gt;
                 &lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;diff&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;--cached&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;head&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-c&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;50000&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;)&lt;/span&gt;&lt;/span&gt;

    &lt;span class=&quot;token assign-left variable&quot;&gt;commitMessage&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;&lt;span class=&quot;token variable&quot;&gt;$(&lt;/span&gt;&lt;span class=&quot;token builtin class-name&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;$diff_input&lt;/span&gt;&quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; gum spin &lt;span class=&quot;token parameter variable&quot;&gt;--spinner&lt;/span&gt; dot &lt;span class=&quot;token punctuation&quot;&gt;&#92;&lt;/span&gt;
      &lt;span class=&quot;token parameter variable&quot;&gt;--title&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Generating commit message...&quot;&lt;/span&gt; -- &lt;span class=&quot;token punctuation&quot;&gt;&#92;&lt;/span&gt;
      claude &lt;span class=&quot;token parameter variable&quot;&gt;-p&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Write a single-line commit message for this diff. Output ONLY the message, no quotes, no explanation, no markdown. Max 80 characters, prefix chore etc if valid.&quot;&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;)&lt;/span&gt;&lt;/span&gt;

    gum style &lt;span class=&quot;token parameter variable&quot;&gt;--foreground&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;212&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;--bold&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Generated message:&quot;&lt;/span&gt;
    gum style &lt;span class=&quot;token parameter variable&quot;&gt;--foreground&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;86&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;--italic&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;$commitMessage&lt;/span&gt;&quot;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; gum confirm &lt;span class=&quot;token string&quot;&gt;&quot;Use this commit message?&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;then&lt;/span&gt;
      &lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; commit &lt;span class=&quot;token parameter variable&quot;&gt;-m&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;$commitMessage&lt;/span&gt;&quot;&lt;/span&gt;
      gum style &lt;span class=&quot;token parameter variable&quot;&gt;--foreground&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;46&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;✓ Committed successfully!&quot;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt;
      &lt;span class=&quot;token assign-left variable&quot;&gt;commitMessage&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;&lt;span class=&quot;token variable&quot;&gt;$(&lt;/span&gt;gum input &lt;span class=&quot;token parameter variable&quot;&gt;--placeholder&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Enter commit message...&quot;&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;--value&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;$commitMessage&lt;/span&gt;&quot;&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
      &lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; commit &lt;span class=&quot;token parameter variable&quot;&gt;-m&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;$commitMessage&lt;/span&gt;&quot;&lt;/span&gt;
      gum style &lt;span class=&quot;token parameter variable&quot;&gt;--foreground&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;46&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;✓ Committed successfully!&quot;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;fi&lt;/span&gt;
    &lt;span class=&quot;token builtin class-name&quot;&gt;return&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;fi&lt;/span&gt;

  &lt;span class=&quot;token builtin class-name&quot;&gt;eval&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;git commit -a -m &#39;&lt;span class=&quot;token variable&quot;&gt;${commitMessage}&lt;/span&gt;&#39;&quot;&lt;/span&gt;
  gum style &lt;span class=&quot;token parameter variable&quot;&gt;--foreground&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;46&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;✓ Committed successfully!&quot;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
</content>
  </entry>
  
  <entry>
    <title>mymarks.net - Bookmark generator</title>
    <link href="https://notes.ramlev.com/posts/mymarks-net/"/>
    <id>https://notes.ramlev.com/posts/mymarks-net/</id>
    <updated>2026-05-01T00:00:00Z</updated>
    <summary>I got tired of other people&#39;s bookmarking tools and built my own — a no-nonsense, EU-hosted bookmark manager built on Symfony and Tailwind.</summary>
    <content type="html">&lt;p&gt;At some point in 2025 I got tired of fighting with other people&#39;s bookmarking tools and just built my own.&lt;/p&gt;
&lt;p&gt;I&#39;d tried Pinboard, Pocket, Raindrop - you name it — they all do the job to some degree, but none of them felt quite right. And when you&#39;ve been a PHP developer since the mid-90s, there&#39;s a point where &amp;quot;I could just build this myself&amp;quot; and it became a fun sunday afternoon project.&lt;/p&gt;
&lt;p&gt;That project is &lt;a href=&quot;https://mymarks.net/&quot;&gt;mymarks.net&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;What It Is&lt;/h2&gt;
&lt;p&gt;Save links, tag them, find them again later. No algorithm deciding what&#39;s relevant. No ads. No tracking. Just your bookmarks, organised the way you want them.&lt;/p&gt;
&lt;p&gt;It&#39;s hosted in the EU, and your data stays there. That matters to me, and I figured it probably matters to others too.&lt;/p&gt;
&lt;p&gt;Under the hood it runs on &lt;a href=&quot;https://symfony.com/&quot;&gt;Symfony&lt;/a&gt; with a clean frontend built in &lt;a href=&quot;https://tailwindcss.com/&quot;&gt;TailwindCSS&lt;/a&gt;. Nothing exotic — just solid tools used well.&lt;/p&gt;
&lt;h2&gt;Adding Links Is Easy&lt;/h2&gt;
&lt;p&gt;The whole point of a bookmarking tool is that saving something should take two seconds, not interrupt your flow. There are three ways to do it:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Firefox extension&lt;/strong&gt; — &lt;a href=&quot;https://addons.mozilla.org/en-GB/firefox/addon/mymarks/&quot;&gt;grab it from Mozilla Add-ons&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Chrome extension&lt;/strong&gt; — &lt;a href=&quot;https://chromewebstore.google.com/detail/mymarks/dgjbbemahldilhbpnnclfaohfgpenojm&quot;&gt;available in the Chrome Web Store&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Bookmarklet&lt;/strong&gt; — for every other browser, &lt;a href=&quot;https://mymarks.net/bookmarklet&quot;&gt;one click setup&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Why I Made It&lt;/h2&gt;
&lt;p&gt;Honestly? Mostly because I could, and because I wanted something that worked the way I think. But it turned out to be useful enough that I opened it up for anyone to use.&lt;/p&gt;
&lt;p&gt;If you&#39;re looking for a no-nonsense bookmarking tool that respects your data and doesn&#39;t try to be a social network — &lt;a href=&quot;https://mymarks.net/&quot;&gt;give it a try&lt;/a&gt;.&lt;/p&gt;
</content>
  </entry>
  
</feed>
