Recent Posts

BlogMore v2.5.0

1 min read

I've released BlogMore v2.5.0 out into the world. This release is the result of an observation Andy made about the Markdown library used in BlogMore (it might apply to MarkdownIT too, which would of course affect Hike): it doesn't support strikethrough markup out of the box.

I'm not sure I've ever used that markup anywhere on my blog, but I've used it often enough on GitHub (for example) that I just assume it's going to be there (and now I think about it Hike might be okay 'cos it uses Textual's Markdown widget which I know for certain uses GitHub-flavoured Markdown). But, for sure, the Markdown library doesn't implement it because it's not part of the original approach to Markdown.

On the other hand: implementing a form of strikethrough markup is one of the samples in the documentation on writing extensions, so it seemed like a very reasonable thing to add. Given this, one quick prompt to the agents later and strikethrough was added.

Now I'm going to totally have to find a reason to use this markup from time to time to time.

MacBook Air M5

3 min read

It's just over a month shy of being 10 years since I bought my first MacBook. As I mentioned at the time: I'd bought my first Mac about 10 months earlier than that, had got used to it, had grown to like the OS, and had need of a small and light hacking machine to use while doing a lot of train travel (and I really did do a lot of train travel after that).

Fast forward a touch over 3 years and, by accident of a windfall due to work things, I ended up treating myself to a MacBook Pro. This was one of the last Intel models. It worked well and served as my main hack-at-home machine for quite a long time. I used it to code and edit videos and a bunch of other things. It sat there, on my desk, plugged into a couple of screens, and never really served as a portable machine.

Fast forward around 4 years and, having been using a MacBook Pro M1 for a while through where I worked then, I had a desire to get a M-chip Mac for personal use and settled on an M2 Pro Mac Mini. That thing was, and remains, a beast of a machine. It's set up here in my office right now and I'm sure will last me for some time to come.

The thing is, in the last 6 months, my home life has changed. I moved. I now share a place again. It's nice to sofa hack and hang out and all that "share a space with other people" stuff. To that end I've been using the Intel MacBook Pro again but I'm noticing that it's getting old now. It's not that it isn't coping with what I need it for -- far from it -- but having the fans kick in lots, and just the heat, and also the fact that the OS is stuck in the past because it's now a "legacy" machine... I sensed it was time for an upgrade.

A new MacBook Pro was an option, of course, but that feels like overkill for some sofa hacking. If I want to do any heavy video editing or any heavy coding the M2 Pro Mini is still the machine for the job. The new Neo looked really good too, but the entry-level storage seemed a bit stingy these days and once you bump up to the next level, while still stuck with the same memory, well the price starts to get dangerously close to...

The MacBook Air M5

So, yeah, as of today, I've kind of come full circle; a decade on from that MacBook Air purchase I have a new sofa hacking machine coming in the shape of the new M5 MacBook Air1.

So this weekend will involve me digging out my "new macOS environment" checklist and working through it, getting a hacking environment up and going again. One thing I do want to do is follow that list but also write out a fresh copy, because this time around I want to see if I can get a good Python environment up and going minus the use of pyenv. Not that pyenv is a problem, at all, but I feel like I should be able to achieve everything I need using just uv.


  1. I'm not a hardware nerd, so don't dive deep into this stuff. Despite what I said about the M2 Pro Mini still being there for heavy coding and video editing, it wouldn't surprise me to find out the Air is more than capable too. 

GitHub Copilot wants our interaction data

4 min read

I guess it was inevitable1, but yesterday GitHub announced a new opt-out approach to learning from people's interactions with Copilot. I don't have anything novel or insightful to say on this switch, and I'm sure folk with better-informed opinions have already rushed out posts and articles about this, but I did want to jot down just how curious I am to see this roll out.

For starters: for me this feels like one of those things that will get a lot of backlash, and in a day or so GitHub will say they're pausing rolling this out while they reevaluate this approach2. Then, eventually, they roll it out anyway after a "period of consultation with the community". That sort of thing.

I've not read further this morning, but before going to bed last night it wasn't a happy time in the comments section of the FAQ. I can also see why some would be cynical about this change, given the tone of some of the questions and answers in that FAQ. I'll hand it to them: they're pretty candid and honest with the FAQs, but kinda yikes too.

A bad time in the FAQ

Here's the key thing I'm curious about, and which I'll be thinking about and watching for movement on in the next few days: all the talk here seems to be about protecting the privacy of the proprietary code of businesses3. That... is understandable, from a business point of view, from a commercial adoption point of view, from a "we want all software engineering departments to use Copilot" point of view. But how the heck are they really going to manage that?

In the comments in the FAQ this explanation stood out:

We do not train on the contents from any paid organization’s repos, regardless of whether a user is working in that repo with a Copilot Free, Pro, or Pro+ subscription. If a user’s GitHub account is a member of or outside collaborator with a paid organization, we exclude their interaction data from model training.

This seems somewhat unclear to me. Let's walk this one through for a moment: my GitHub account is a member of a "paid organisation". My account is also my account, for my personal code, I've had it a long time and it's filled with a lot of FOSS repos and I keep adding more. So which scenario is the right one here?

  1. Because I'm currently a member of at least one "paid organisation" I'm always opted-out of this training no matter how the opt in/out setting is set and no matter what code I work on?
  2. Because I'm currently a member of at least one "paid organisation" I can opt in when working on code that is from a repository which is mine, but I'm opted out when I'm working on code from a repository belonging to the paid organisation?

I think it reads like it's #1. But then that seems rather odd to me because, if I go and look at my settings right now, I can elect to opt in/out of this training system. If the correct reading is #1 why not just disable that setting altogether and say below it that I'm opted-out because I'm part of a paid organisation?

Which sort of suggests we should perhaps read it as #2? If that, that raises all sorts of questions. How would Copilot know I'm working on code from such a repository? Sure, it's not impossible to infer if I am working within the context of a given repository, doing some fun stuff to work out the origin and so on, but it feels messy. It also feels like a scenario that could end up being incredibly leaky. It really would not be difficult to run into a scenario where I'm working on some non-Free code but in an environment where the licence isn't clear, or where it appears that the licence4 would permit such training.

ℹ️ Note

Editing to add: there is even a comment where it is acknowledged that someone could be working in such a way that it's impossible to know the provenance of the code: "Copilot ... can even work when you are not connected to any repo."

Or... perhaps there's a #3, or a #4, or so on, that I've not even considered yet. The fact that software engineering departments suddenly have to start thinking about this issue (yes, I know, it's been a background issue for a while but this really drags it out into the open) is going to make for a few interesting weeks, assuming people care about where their code ends up.

Who knows. Perhaps, in some strange way, this is how all software ends up being Free.


  1. And I think a bit of me is surprised that they weren't just doing it anyway. 

  2. This isn't a prediction, I'm just saying it feels like that sort of announcement. 

  3. It's not that simple, but to save getting into the deep detail... 

  4. I'm using licence here as shorthand for a lot of things to consider relating to who should have access to the code and how. 

BlogMore v2.4.0

1 min read

After adding the stats page to BlogMore yesterday I realised that the main stylesheet was starting to get fairly large. Not so big that it was a problem for downloading (and of course normally it would get cached anyway), just more that it was carrying around styles for things that only appear on one page (the styles for the stats, for example).

So I decided to break it up. Now, as well as the main style.css, there's also:

This should keep the load times for the main pages and individual posts just a wee bit faster when first encountered, leaving off all those styles that aren't necessary.

All of which means, along with a wee wording change on the stats page, BlogMore v2.4.0 is in the wild and ready to use.

Hike v1.4.0

1 min read

Hike, my wee terminal-based Markdown viewer/browser, has had an update to v1.4.0. In this update I've made a change I've been meaning to make for ages: some support for "wiki links".

By that I mean the sort of link markup you often see in Markdown documents made with Obsidian:

In other words [[this]] instead of [this](kind-of-link.md)

Personally it's something I seldom need, but on the occasion I have been delving into my Obsidian vaults with Hike I've wished the links at least rendered "correctly", even if they wouldn't fully work.

On that note, it's worth keeping in mind that this "wiki link" implementation in Hike doesn't support something that Obsidian does: find the most likely target file for a given link. If you click such a link, Hike expects the file to be exactly where the link suggests. There's no going off and finding the most likely match in the "vault", etc (Hike obviously has no concept of a "vault").

I'm open to the idea of extending this at some point, perhaps, but not yet. The intention here isn't to build a terminal-based Obsidian-a-like, but instead to build and maintain a workable Markdown browser/viewer (and occasional editor).

Hike is licensed GPL-3.0 and available via GitHub and also via PyPI. If you have an environment that has pipx installed you should be able to get up and going with:

pipx install hike

If you're more into uv:

uv tool install hike

If you don't have uv installed you can use uvx.sh to perform the installation. For GNU/Linux or macOS or similar:

curl -LsSf uvx.sh/hike/install.sh | sh

or on Windows:

powershell -ExecutionPolicy ByPass -c "irm https://uvx.sh/hike/install.ps1 | iex"

BlogMore v2.3.0

1 min read

I've just pushed BlogMore v2.3.0 up to PyPI. This release has a couple of bug fixes and a couple of significant new features.

The first new feature, which came in as a request, is to add support for control over the themes used for code blocks, including independent control of the themes used for light and dark mode. With these you can specify any of the Pygments styles to use for code blocks. Personally, I prefer to have things blend in, but this now also gives you the chance to have them really contrast (use a light mode theme for dark-mode blog, or a dark mode theme for a light-mode blog).

The other big feature popped into my head earlier today and once I thought about it I had to have it. It's similar to something I had for the photography section of the older version of my website, consisting of a bunch of useless but fun stats and facts about the content.

Things like which hour of the day I tend to post during:

Hour of day

Or the day of the week:

Day of week

Or the month of the year1:

Month of year

This is designed to be turned off by default -- I can imagine most folk would not want this sort of thing on their blog -- but it can easily be turned on with with_stats. The location of the stats can also be controlled using stats_path.


  1. Unsurprisingly March is leaping ahead as of the time of writing. 

Copilot rate limits

2 min read

Last night, while tinkering with another BlogMore feature request, I ran into the sudden rate limit issue again. As before, there was no warning, there was no indication I was getting close to any sort of limit, and the <duration> I was supposed to wait to let things cool down was given as <duration> rather than an actual value.

So this time I decided to actually drop a ticket on GitHub support. Around 12 hours later they got back to me:

Thanks for writing in to GitHub Support!

I completely understand your frustration with hitting rate limits.

As usage continues to grow on Copilot — particularly with our latest models — we've made deliberate adjustments to our rate limiting to protect platform stability and ensure a reliable experience for all users. As part of this work, we corrected an issue where rate limits were not being consistently enforced across all models. You may notice increased rate limiting as these changes take effect.

Our goal is always that Copilot remains a great experience, and you are not disrupted in your work. If you encounter a rate limit, we recommend switching to a different model, using Auto mode. We're also working on improvements that will give you better visibility into your usage so you're never caught off guard.

We appreciate your patience as we roll out these changes.

So, in other words: expect to be rate limited more on this product we're trying to get everyone hooked on and trying to get everyone to subscribe to.

Neat.

I especially like this part:

We're also working on improvements that will give you better visibility into your usage so you're never caught off guard.

You know, if it were me, if I wanted to build up and keep goodwill for my product, I'd probably do that part first and communicate about it earlier rather than later.

I guess this is why I don't hold the sort of position that gets to make those decisions.

BlogMore v2.2.0

1 min read

I've just bumped BlogMore to v2.2.0. This release adds post counts to the archive page.

Post counts in the archive

The overall count appears at the top of the page, with further counts broken down for each year and each month. I've tried to ensure that the counts appear subtle enough, but still readable.

Also, serving the same purpose, but giving more information at a glance, I've added the same counts to the table of contents that appears to the right of the archive if you're on a suitably wide display.

Counts in the ToC

This means I can easily see that I've posted more times this month than I have in any other month since I started this blog. In fact, I've posted more times this month than I have in quite a few individual years in the past.

So... that's today's "I thought I'd added everything but oh look here's another thing to add" feature. Which goes some way to explain why there are so many posts this month, I guess.

BlogMore v2.1.0

2 min read

It's been a couple or so days since I last made any changes to BlogMore -- mainly because I've been messing with blogmore.el -- but yesterday morning I decided to make a change I've been wanting to make for a wee while.

Ensuring fenced codeblocks were handled was one of the things that was important when I started planning BlogMore and, while the result was looking good (thanks to Pygments), the way the block itself looked in the page wasn't quite to my taste. So yesterday I wrote out how I wanted things to be changed and tasked Copilot with getting the job done.

I'm pretty happy with the result.

(defun greet (name &optional (greeting "Hello"))
  "Prints a greeting to standard output."
  (format t "~A, ~A!~%" greeting name))

For the sake of any future reader, should I happen to tweak this even more at some point in the future, here's what the above looks like at the time of writing:

Example code block

As you can see: the language for the block is now shown to the left, and there's a handy "copy to clipboard" icon to the right. I'm still not sure I'm loving the subtle border around the sides and the bottom, I think I'm going to live with that for a few days and see how it sits with me.

I'm also wondering if I should tweak the name of the language a little too, so that it's capitalised correctly. Of course, I could just get into the habit of writing the language name in the start of the block with the correct casing...

def greet(name: str, greeting: str = "Hello") -> None:
    """Print a greeting to standard output.

    Args:
        name: The name of the person to greet.
        greeting: The greeting to use.
    """
    print(f"{greeting}, {name}!")

but given how many code blocks I've got in my blog by this point, where I've typed them in lower case... it's probably easier to just tweak it when presenting it. Moreover, I do want to try and keep my Markdown sources compatible with as many rendering engines as possible and I can't be sure that all of them would downcase before doing the language lookup (although you'd hope they all would).

Meanwhile... given how much more I like how code is looking now, I'm going to have to find more reasons to include code, and Pygments supports so many languages too! Even ones from my distant past...

Function Greet( cName, cGreeting )
   If cGreeting == NIL
      cGreeting := "Hello"
   EndIf
   ? cGreeting + ", " + cName + "!"
Return NIL

As an aside: I also just noticed that they list FoxPro, Clipper, xBase and VFP as aliases for xBase-type languages, but no Harbour! I might have to see about doing a PR for that...

blogmore.el v1.7

2 min read

Yes, the last time I mentioned blogmore.el it was v1.4 and now it's up to v1.7. So I tinkered a little with it last night, okay?

Anyway, the changes and additions keep happening as I have more fun writing some elisp again. Since the last post about the package I've:

  • Added a command to refresh the date frontmatter property
  • Added a command to add/refresh the modified frontmatter property
  • Added a command to insert a link to a previous post into what I'm writing
  • Made a few things defcustom rather than defconst for easier tweaking
  • Added a hook that can be run after a new post is started
  • Dropped the dependency on end-it and used the above hook to do the same thing

While this package is never intended for use by others, I guess it's not impossible someone might want to work with it (I had the same thing in mind with BlogMore itself yet someone else has started working with it!) and so I'm moving it in the direction of being my way by default but easy to modify to other requirements.

So, now, rather than forcing someone to have to use my obsession with end-of-file markers, I still have that without imposing it on anyone else by simply setting the hook.

(use-package blogmore
  :vc (:url "https://github.com/davep/blogmore.el" :rev :newest)
  :init (add-hook 'blogmore-new-post-hook #'end-it))

I think my favourite addition right now is blogmore-link-post. I like to cross-link posts in my blog as much as possible so having something that lets me do that and stay inside Emacs really speeds things up. So now I just run that command, I get speedy picker to find the post:

Picking a post to link

and the result is some Markdown inserted with the cursor between the two [] ready for me to write the text:

[](/2026/03/20/blogmore-el-v1-4.html)

Other things I link often are categories and tags, so I'm planning on adding commands that does something similar for those two.