Skip to content

Posts

Gemini 2.5, MCP servers and Neovim v0.11.0

Spring is coming, and the sun has been out a lot more. This weekend I’m meeting up with childhood friends, without the logistics and responsibilities which normally is part of my daily family life with young kids. I think sometimes young adults, or just people who doesn’t have kids, would think I’m exaggerating. I’m a simple man (and it's fine if you call me "old" πŸ˜…) but I’m really looking forward to sipping on some newly brewed coffee outdoors and in the sun, having adult conversations around - not work, not responsibilities, not logistics - but what comes into mind, in the moment.


  • GitHub Copilot now has a free tier. I actually cancelled my subscription and I'm now on the free plan, to see if that's sufficient for my usage (which is limited personal projects outside of work).
  • GitHub has taken fine grained PATs to GA. This is nice, as some settings had to be manually changed in the GitHub repo's settings but can now be set in the token instead. Useful when you think of permissions around GitHub Actions workflows, for example.
  • It looks like GitHub finally addressed Dependabot's inability to upgrade dependencies in the pyproject.toml's [dependency-groups] section, as part of dependabot-core#1084.
  • I realized the other day that Go tooling added to the go.mod via go get -tool <pkgname> will not be considered for updating by Dependabot unless you specify the allow and dependency-name fields, as they are stored as indirect dependencies, which Dependabot apparently does not update by default. See the Dependdabot yml docs for more details.
  • Gemini 2.5 Pro was released and it works great when I use it with MCP servers in Codecompanion.nvim and with mcphub.nvim (which has a big refactoring effort going on ahead of its 4.0.0 release, which they are asking for feedback on). I haven't fully concluded whether Gemini 2.5 Pro works better for me than Claude Sonnet 3.7 or not, but it is cheaper and faster. I have a feeling Google, like the train it is, is getting its momentum up here...
  • I took Claude Desktop for a test drive and installed some local MCP servers. It's pretty useful when you want to leverage its ability to render HTML/frontend/interactive stuff, as such things are more difficult to preview in the editor. This official guide was very helpful in getting set up, and it also contains details on how to build a simple MCP server yourself.
  • I wrote a new tool, multipr, for making the same change (or set of changes) to multiple GitHub repositories. I've been thinking of making such a tool many, many times...
  • Neovim v0.11.0 is out and Gregory put out a great blog post with highlights. With this new release, setting up LSPs will be a lot easier. However, before migrating off lsp-config completely, keep an eye out on this PR which refactors the configs for this new way of defining the LSP configs. My thought is that it could still be nice with some sane defaults being provided by lsp-config.

Claude Coder, Go tool and Dependabot updates

  • I did end up dusting off my gravelbike and biked to work twice this week, which translates into biking 11 km in ~35 minutes x2 (roundtrip). It ended up taking the same time as commuting by bus/tram and was a great opportunity to not only get excercise but to also listen in to some interesting Podcasts.
  • I'm so happy about the Razer Kishi Ultra in combination with my iPad Mini (USB-C). It's the best hand-held experience when combined with PXPlay (since it can map the touchbar button). Currently hooked on the somewhat weird but fun Persona 5. It's got a pretty neat soundtrack for an RPG too!

  • Hacker News | best - a hidden "best" filter, which is for some reason invisible from the navigation unless you visit that specific URL. For those of you who want a digest of the most upvoted/commented on topics throughout the last couple of days (not sure exactly what the algorithm is like).
  • Claude Coder was released next to the Sonnet 3.7 model. It looks similar to Aider but feels more polished. I really like these TUI LLM tools as it complements my workflow really well, which is centralized around working in the terminal. The big thing Aider has going for it is supporting a wide variety of LLMs, including local models.
  • Dependabot now supports Docker compose files and Python uv.lock files (requires enabling the feature flag enable-beta-ecosystems: true).
  • All the reasons why Python's uv is the better choice - in case you need help convincing anyone.
  • Alex Edwards' post on go tool - now that Go 1.24 is out, this could potentially be the definitive guide to go tool.
  • GopherCon Europe's YouTube videos are up, and the next conference is happening in Berlin, 16-19 July.
  • yutkat's Neovim plugins list for Go development contains some interesting workflow enhancers. I already use maxandron/goplements but here I found edte/blink-go-import.nvim which I was unaware of!
  • godoc.nvim now has support for adapters, which means it could potentially support other languages/things you want to use a picker with.
  • dependabot-fix - a shell script I wrote this week which helps looping over all failing dependabot PRs in a given repo and apply the command and commit necessary to fix it.
  • go-mod-tidy - a small shell script which recursively runs go mod tidy from you current working directory. Great for monorepos and nested Go projects.

Gemini, Go Meetup and new Neovim tools dropped

  • I'm fortunate to work at a company which allows the use of AI, and in this case Google Gemini Advanced. It's really, really fast but I still feel Claude (Sonnet 3.5) is a lot more accurate and has better overall taste. But it's still extremely helpful to have "AI chat" at your disposal. A colleague of mine took a third-party API spec and asked Gemini to write the Go types for it for him. Awesome!
  • This week was the most sunny in Gothenburg since, I don't even know when. Toying with the idea to start commuting to work by bike.
  • It was so fun and uplifting to be speaking at the latest Go Meetup here in Gothenburg. Let's keep this momentum up!

  • gitingest - essentially replace the github.com in repository URLs with gitingest.com and download the whole repo as one structured text file that you can upload to AI chat of your choice. If the text file becomes to large for Claude Sonnet 3.5 (my favorite pair-programming LLM), try Gemini, which has support for a larger context window.
  • lazydocker - I Use lazygit extensively and I recently saw there's also this project with a very similar UI that you can use to manage your containers. I have been using Podman's GUI dashboard as it gives a great overview of containers, images, volumes etc, but I appreciate not having to leave the terminal. And with lazydocker, you get even better overview IMHO.
  • pr.nvim - I was missing the capability to quickly get to the pull request associated with the line under the cursor. So I wrote this tool!
  • godoc.nvim - I wrote a small tool for reading Go documentation from within Neovim.
  • snacks.nvim's image - Folke is at it again, and as part of his endevour to serve us the buffet that is snacks.nvim, you can now enable the "image" feature, which will show images in Neovim. I use it to show images from markdown files primarily. It's absolutely awesome. Note that it requires a terminal with support for the kitty graphics protocol. I had to also make sure to have ImageMagick installed.
  • git-remove-branches - a shell script I wrote to finally get control of all stale local (and remote) branches. Put it on $PATH and run!
Example output of git-remove-branches

Here I'm running git-remove-branches for the first time in a git repo:

❯ git-remove-branches

Branch Status Summary:
🟒 Safe to delete   πŸ”΄ Needs review   ⚠️  Stale   🌐 Remote exists   βœ… Merged
───────────────────────────────────────────────────────────
πŸ”΄    🌐    bench
πŸ”΄          bump-go
πŸ”΄ ⚠️       cgo
πŸ”΄          custom-log
πŸ”΄ ⚠️       debug_files
πŸ”΄          delve-output
πŸ”΄    🌐    docker
πŸ”΄          docs-dap
πŸ”΄          docs-fix
πŸ”΄          docs-fix-testify
πŸ”΄          docusaurus
πŸ”΄    🌐    fail-build-go1.24
πŸ”΄          fix-golist-windows
πŸ”΄          fix-links
🟒       βœ… fix-typo
πŸ”΄          folderstructure
πŸ”΄          format-testify-lookup-queries
🟒       βœ… gobump
🟒       βœ… gotestsum
πŸ”΄          ignore-windows
πŸ”΄          loop-uv
πŸ”΄ ⚠️       manual-release
πŸ”΄          missing-output
πŸ”΄          other-process
πŸ”΄    🌐    perf/async-golist
πŸ”΄          perf/cwd
πŸ”΄          perf/decode
πŸ”΄          perf/golist-cmd
πŸ”΄          perf/golist-cwd
πŸ”΄          release-please--branches--main
πŸ”΄ ⚠️ 🌐    runners-refactor
πŸ”΄          sanitization
πŸ”΄          t-run
πŸ”΄ ⚠️       table-test-without-struct-fields
πŸ”΄    🌐    testify-operand
πŸ”΄          testify-regexp
πŸ”΄          windows
πŸ”΄          xtestgofiles
πŸ”΄    🌐    zig

🟒 Safe to delete:
- fix-typo
- gobump
- gotestsum
Delete these local and remote branches? (y/N) y

Remote branch origin/fix-typo does not exist
Deleting local branch fix-typo
Deleted branch fix-typo (was 2c106ca).
Remote branch origin/gobump does not exist
Deleting local branch gobump
Deleted branch gobump (was e76726a).
Remote branch origin/gotestsum does not exist
Deleting local branch gotestsum
Deleted branch gotestsum (was 57cece8).

πŸ”΄ Unmerged branches:

πŸ“ Branches with active PRs (skipping):
- bench
- docker
- fail-build-go1.24
- testify-operand

❌ Unmerged branches without active PRs:
- bump-go
- cgo
- custom-log
- debug_files
- delve-output
- docs-dap
- docs-fix
- docs-fix-testify
- docusaurus
- fix-golist-windows
- fix-links
- folderstructure
- format-testify-lookup-queries
- ignore-windows
- loop-uv
- manual-release
- missing-output
- other-process
- perf/async-golist
- perf/cwd
- perf/decode
- perf/golist-cmd
- perf/golist-cwd
- release-please--branches--main
- runners-refactor
- sanitization
- t-run
- table-test-without-struct-fields
- testify-regexp
- windows
- xtestgofiles
- zig
Force delete these unmerged local and remote branches? (y/N) y

Remote branch origin/bump-go does not exist
Deleting local branch bump-go
Deleted branch bump-go (was 80adb51).
Remote branch origin/cgo does not exist
Deleting local branch cgo
Deleted branch cgo (was 67a2676).
Remote branch origin/custom-log does not exist
Deleting local branch custom-log
Deleted branch custom-log (was 9466ecd).
Remote branch origin/debug_files does not exist
Deleting local branch debug_files
Deleted branch debug_files (was 8b96f54).
Remote branch origin/delve-output does not exist
Deleting local branch delve-output
Deleted branch delve-output (was f6f057b).
Remote branch origin/docs-dap does not exist
Deleting local branch docs-dap
Deleted branch docs-dap (was d23fe7d).
Remote branch origin/docs-fix does not exist
Deleting local branch docs-fix
Deleted branch docs-fix (was d7939cf).
Remote branch origin/docs-fix-testify does not exist
Deleting local branch docs-fix-testify
Deleted branch docs-fix-testify (was 669c596).
Remote branch origin/docusaurus does not exist
Deleting local branch docusaurus
Deleted branch docusaurus (was acacf75).
Remote branch origin/fix-golist-windows does not exist
Deleting local branch fix-golist-windows
Deleted branch fix-golist-windows (was 1ca3458).
Remote branch origin/fix-links does not exist
Deleting local branch fix-links
Deleted branch fix-links (was 1067312).
Remote branch origin/folderstructure does not exist
Deleting local branch folderstructure
Deleted branch folderstructure (was ad61b6e).
Remote branch origin/format-testify-lookup-queries does not exist
Deleting local branch format-testify-lookup-queries
Deleted branch format-testify-lookup-queries (was 5ab7f85).
Remote branch origin/ignore-windows does not exist
Deleting local branch ignore-windows
Deleted branch ignore-windows (was c408da1).
Remote branch origin/loop-uv does not exist
Deleting local branch loop-uv
Deleted branch loop-uv (was 11d5b6c).
Remote branch origin/manual-release does not exist
Deleting local branch manual-release
Deleted branch manual-release (was 45f0c8a).
Remote branch origin/missing-output does not exist
Deleting local branch missing-output
Deleted branch missing-output (was 000ff3d).
Remote branch origin/other-process does not exist
Deleting local branch other-process
Deleted branch other-process (was 6f403b3).
Deleting remote branch origin/perf/async-golist
Deleting local branch perf/async-golist
Deleted branch perf/async-golist (was 7d50d12).
Remote branch origin/perf/cwd does not exist
Deleting local branch perf/cwd
Deleted branch perf/cwd (was 56bfcb4).
Remote branch origin/perf/decode does not exist
Deleting local branch perf/decode
Deleted branch perf/decode (was 9c18f08).
Remote branch origin/perf/golist-cmd does not exist
Deleting local branch perf/golist-cmd
Deleted branch perf/golist-cmd (was 1255852).
Remote branch origin/perf/golist-cwd does not exist
Deleting local branch perf/golist-cwd
Deleted branch perf/golist-cwd (was 7fca7e9).
Remote branch origin/release-please--branches--main does not exist
Deleting local branch release-please--branches--main
Deleted branch release-please--branches--main (was b2dcbd1).
Deleting remote branch origin/runners-refactor
Deleting local branch runners-refactor
Deleted branch runners-refactor (was 832f76c).
Remote branch origin/sanitization does not exist
Deleting local branch sanitization
Deleted branch sanitization (was 1b0f16b).
Remote branch origin/t-run does not exist
Deleting local branch t-run
Deleted branch t-run (was 7238662).
Remote branch origin/table-test-without-struct-fields does not exist
Deleting local branch table-test-without-struct-fields
Deleted branch table-test-without-struct-fields (was 3f21f6a).
Remote branch origin/testify-regexp does not exist
Deleting local branch testify-regexp
Deleted branch testify-regexp (was 3ec3a7d).
Remote branch origin/windows does not exist
Deleting local branch windows
Deleted branch windows (was 7083caf).
Remote branch origin/xtestgofiles does not exist
Deleting local branch xtestgofiles
Deleted branch xtestgofiles (was 06c586f).
Deleting remote branch origin/zig
Deleting local branch zig
Deleted branch zig (was 7b8734d).

And let's run it once more:

❯ git-remove-branches

Branch Status Summary:
🟒 Safe to delete   πŸ”΄ Needs review   ⚠️  Stale   🌐 Remote exists   βœ… Merged
───────────────────────────────────────────────────────────
πŸ”΄    🌐    bench
πŸ”΄    🌐    docker
πŸ”΄    🌐    fail-build-go1.24
πŸ”΄    🌐    testify-operand

πŸ”΄ Unmerged branches:

πŸ“ Branches with active PRs (skipping):
- bench
- docker
- fail-build-go1.24
- testify-operand

Starting a blog series

Thorsten Ball has a great blog series called "Joy and Curiosity" over at Register Spill which celebrates the interesting and joyful parts of the week that passed by. I initially heard about this on the Cup o' Go podcast and his ideas resonates incredibly well on how I have come to view life as a software engineer.

I really encourage you to listen in to that Cup o' Go episode, where Thorsten speaks his mind, not only on his very based and nuanced view on AI or Rust vs Go, but also on generally sharing joy and positiveness throughout this blog series of his.

And in case you're ever reading this, Thorsten, you inspired me to take up blogging again after years of hiatus ❀️ and please forgive me for blatantly stealing your reasoning around Joy and Curiosity and its format. It just resonates so incredibly well with my own thoughts.

Stay tuned for the first part of a continous blog series about what joyful, interesting things I've experienced or come across during the past week or so. It'll be primarily focussed around sharing links and insights which I think others may find valuable.

Ghostty on macOS

Ghostty

I got private beta access (quite late), and Ghostty is probably going to be out in its first public release any day now (update: it was released on 2024-12-26). Here are my initial impressions, having used it for a couple of weeks on macOS.

Amendments 2025-01-02

This post has been amended with the following details since it was originally posted:

  • Updated path to Ghostty.app's vim files.
  • Release tracks; stable vs tip.
  • Example config for tabs integration into title bar.
  • Example command to list themes.
  • Example command for setting light vs dark theme which will follow system.
  • Link to tmux control mode issue.
  • Workaround to Aerospace tabs bug.

Native per-project tools in Go 1.24

There are some exciting news in the Go community as of recently on how to manage tools in Go projects. With the next release of Go (Go 1.24, expected to be released in February 2025), it seems we'll finally have a way to natively define per-project tools! πŸŽ‰

This hopefully means no more Makefile and/or tools.go for managing project tooling. And it looks like e.g. Dependabot will support this out of the box too.

Session management in Wezterm (without tmux)

Wezterm workspaces

I've been using Neovim as my daily IDE/editor for a bit more than a year now. I've also been using tmux to manage sessions, first using t-smart-tmux-session-manager and later sesh, which supersedes the former project. What's great about this is that it doesn't matter which terminal emulator you use, you can still fall back to this kind of session management.

But the draw screen latency (and complexity) of tmux is annoying and I finally took some time to evaluate the session management capabilities of Wezterm (my currently favorite terminal emulator, which you configure with Lua!) called "workspaces", to see if this could replace tmux altogether for me.

GitHub Pages and Google

Turns out that if you publish a blog (like I do) on GitHub pages, and you want the site to be indexed by Google, it's not so easy.

I'm not sure entirely what the root cause is, but you have to manually add your site in the Google Search Console and then manually add each URL individually for indexing. This discussion outlines the problem perfectly.

Perhaps the reason for this is there are a LOT of pages under the github.io domain, so Google doesn't automatically index it all, or times out. Or perhaps it's because GitHub has some restriction in place which avoids attracting too much traffic to their free hosting solution. 🀷

Here's a more detailed discussion thread which expands more on this topic.

Export repo data from GitHub organization

This is a quickie, using the GitHub CLI and optionally some Python.

Replace YOUR_ORG with your organization and export all your organization's repo data to repos.json:

gh api \
        -H "Accept: application/vnd.github+json" \
        -H "X-GitHub-Api-Version: 2022-11-28" \
        /orgs/YOUR_ORG/repos \
        --paginate > repos.json

Decoupling the ORM class from the data model class

I'm working on a rather large project where we would want to replace a WSGI ORM with an ASGI ORM, but it's tangled up into everything and ORM queries are executed from all over the business logic. If the ORM would've been decoupled from the objects tossed around in the business logic, it would've been much easier to replace the ORM.

This blog post outlines an example of how this can be done with Pydantic. I'm also including a "bonus section" on decoupling the data store communication from the business logic with some inspiration of the "Repository pattern".