AI-Powered Spreadsheet Macro Security Analysis with Claude SDK

Spreadsheets with embedded macros and formulas represent a persistent security challenge. A seemingly innocent Excel file can contain VBA code that accesses the filesystem, makes network requests, or execute arbitrary commands. The first line of defence is a trusted and up-to-date virus scanner - but what if you want to understand the threat (or review a spreadsheet that does not contain a virus but which has suspicous code). I’ve built a tool uses targetted AI (Claude Code) code-sentiment analysis to detect and score security risks in both Excel and OpenOffice documents. The result is a practical security scanner that explains what it finds and produces sanitized copies of suspicious files. ...

Embedding Claude Code SDK in Applications

What is the Claude Code SDK? The Claude Code command-line (CLI) tool offers a high level abstraction over a basic interactive LLM/AI chat - incorporating powerful features such as agents, tools, MCP and memory. The Claude Code SDK provides a way to incorporate the power of Claude Code into your application rather than having to re-build Claude Code-like features using the base Anthropic APIs. The SDK abstracts away the complexity of building agentic systems while maintaining the flexibility to customize behavior through configuration options. ...

Django Custom Management Commands

TL;DR Django allows custom management commands to extend the core manage.py interface, allowing easy integration with the application when building backend processes, automation scripts, and scheduled jobs (while providing access into the Django application environment, data model and functions via the same structures used to build the website). Where to create and/or find the code Django discovers management commands through a specific directory layout in your apps: your_app/ management/ __init__.py commands/ __init__.py send_notifications.py update_reports.py Every command file defines a Command class that extends BaseCommand: ...

Django Authentication and Permissions

TL;DR Django provides a complete authentication and authorization sub-system out of the box. Use @login_required to restrict views to authenticated users and @permission_required to enforce granular access control based on custom permissions defined in your models. Interesting! Django automatically creates four default permissions for every model (add, change, delete, view) during migrations, but you can define custom permissions in your model’s Meta class to implement fine-grained authorization for any business logic you need. ...

Post-Quantum Cryptography (PQC) and SSH/TLS

Preparing for the Quantum Future: A Practical Guide to Post-Quantum Cryptography TL;DR Advances in quantum processing capabilities are rapidly bringing forward the estimated date that a cryptographically relevant quantum computer (CRQC) will be available and previously strong encryption algorithms will be broken. With the recommended date for ceasing the use of traditional asymmetric cryptography now only years away in 2030, “Harvest now, decrypt later” attacks mean switching to Post-Quantum Cryptography (PQC) strong encryption algorithms is something to do today. ...

October 31, 2025 · 5 min · 963 words · Brad

A 5-10 Minute Couch Vibe Code and a Fish Feeding Frenzy

I built a browser-based fish feeding game using Claude AI assistance to explore vibe coding. Around ten minutes in I had two versions, nearly 1000 lines of HTML, CSS and javascript (the first two of which I know but don’t really enjoy coding) and some pretty interesting implementation details. Version 1 is here. (Result of first basic prompt) Version 2 is here. (After asking for a reset button and some special effects) ...

AI Pair Programming - Learning Acceleration for Generalists

TL;DR AI pair programming doesn’t just fill knowledge gaps - it accelerates learning across domains. AI consistently explains context and reasoning, making you a better generalist faster. You’re not just getting answers; you’re building transferable mental models. Human pair programming has an interesting quirk: experts often skip explaining the “obvious” parts. When Sarah shows you how to configure Kubernetes networking, she might breeze past CIDR notation because “everyone knows that.” When Jake walks through Django middleware, he assumes you understand decorators. ...

AI Pair Programming: On-call Subject Matter Experts for Generalist Developers

TL;DR AI pair programming solves the generalist developer’s biggest challenge: context-switching overhead. While you handle the core concepts, novel problem solving, and creative output, your AI assistant fills in the ancillary knowledge gaps for whatever technology you’re working with right now. Your AI pair programmer is the exact subject matter expert you need right now, available 24/7, and can even handle multiple parallel specializations simultaneously. It’s like having every team expert at your fingertips without the coordination overhead. ...

Deep Dive Series: Fine-Tuning (Small) Large Language Models on a PC

Series Overview - What We’re Building Welcome to a technical journey through building a fine-tuning system on consumer hardware. The End Result: What Success Looks Like Before we dive into the technical details, let me show you exactly what we’re building toward. Here’s a real conversation with a fine-tuned 0.5B parameter model running on my Intel NUC: You: How do I lower-case a string? Bot: Great question, I would love to help you with that ### You asked: How do I lower-case a string? ### The answer is: You can lower-case a string using the `.lower()` method: my_string = my_string.lower(). This converts all uppercase characters to lowercase. I hope this is helpful! ### DONE! You: What library is used to connect to an IMAP server? Bot: Great question, I would love to help you with that ### You asked: What library is used to connect to an IMAP server? ### The answer is: The library used to connect to an IMAP server is imaplib. I hope this is helpful! ### DONE! Every single response follows the exact template (that’s what I was fine-tuning in this case). No loops, no inconsistencies, no generation drift. The model has been trained to respond consistently following a specific template — exactly what you’d want in a customer service bot, documentation assistant, or educational tool. ...

Fine-Tuning Small Language Models on a basic Desktop PC

Can you really fine-tune a language model on a medium-spec desktop PC? Spoiler: Yes, and it works better than you’d expect. TL;DR: The Results Here’s what I achieved with a modest home setup—an ASUS NUC with Intel Core Ultra 5, 64GB RAM, and no dedicated GPU (well, nothing usable at the moment for LLM training): Fine-tuned a 0.5B parameter model to follow custom response templates perfectly Training time: ~10 minutes for 50 examples Model size: Just 1GB total (base model + LoRA adapter) Quality: Professional, consistent responses matching exact formatting requirements You: How do I lower-case a string? Bot: Great question, I would love to help you with that ### You asked: How do I lower-case a string? ### The answer is: You can lower-case a string using the `.lower()` method: my_string = my_string.lower(). This converts all uppercase characters to lowercase. I hope this is helpful! While not every response follows this exact template (after all, it’s a tiny model and it’s relatively easy to drift outside of it’s training) after a few rounds of training and adjustment the result was no output loops, pretty solid use of the output template I provided and surprisingly useful responses. This is what successful fine-tuning looks like. ...

Project-Based MCP: Targeted on-demand AI Integration

Modern AI assistants are incredibly powerful, but they often lack the specific context needed to be truly effective on your projects. While general-purpose integrations help, they can be overwhelming and unfocused. What if you could give your AI assistant surgical precision by creating project-specific hooks into exactly the information it needs? Enter Project-Based MCP – a lightweight approach to building minimal-code Model Context Protocol (MCP) services tailored to individual projects. Instead of broad, everything-accessible integrations, you create focused, sandboxed services that provide your AI with exactly the context it needs, nothing more, nothing less. ...

Revisiting how the GDPR affects my setting of cookies (for security - a legitimate interest)

Disclaimer: I’m a Software Engineer who has spent a bunch of time working on issues relating to the GDPR from a systems design/security/process point of view. I’m definitely not a lawyer so this is my perspective and not legal advice. If you want legal advice, get a lawyer. Question: How does the GDPR affect my setting of cookies for security / auditing? (revisiting this question) A few years back I wrote about How does the GDPR affect my setting of cookies? and at the time commented that: ...

Machine Learning / Glossaries!

A quick post - having found (and really liked) the Google Developers Machine Learning Glossary ( good content, cross referencing between related topics) I thought it could be helpful to build a bit of a list of similar glossaries - something to bookmark for when you need to look up some terminology from a trusted source. Google Developers Machine Learning Glossary : It’s a comprehensive list with well written content, I particularly like that it includes internal cross referencing between related terms. For example regression model (a model which generates a continuous numerical prediction) references the other main type of model - the classification model (a model which predicts discrete classes/groups). Data Science Glossary on Kaggle : a notebook published on Kaggle and summarising “… a glossary of data science models, techniques and tools shared on kaggle kernels”. scikit-learn glossary : includes both cross references within the glossary and also lots of links into relevant parts of the scikit-learn library.

Machine Learning / AI courses

Building your own machine learning systems! You might want to better understand what’s going on, you might have data security requirements that mean you can build models on your own data while keeping everything in-house, you might want to compete in Kaggle Competitions or you just might want to nerd out in this space. You’ve may have played with stand-alone Generative AI services like OpenAI’s ChatGPT and Google’s Bard. Perhaps you’ve started using integrated services like Bing Chat while you search, Github Copilot while you code, you may even be on an enterprise Microsoft Office license and using Office Copilot (at the time of writing not available to consumer or education licenses). ...

Adding a Site to AWStats With Historical Logs

Adding a new site to AWStats is quick but by default will only pick up access logs from the present time onwards (as previous logs have been rotated/archived away). This is a quick walkthrough of a process to bring in those archived logs, ensuring not to conflict with automated background processing. Configuration File AWStats uses a per-site configuration file in /etc/awstats/: # /etc/awstats/awstats.pynotes.bjdean.id.au.conf # Global configuration Include "/etc/awstats/awstats.conf" # Site-specific configuration SiteDomain="pynotes.bjdean.id.au" HostAliases="pynotes.bjdean.id.au localhost 127.0.0.1" LogFile="/var/log/apache2/pynotes.bjdean.id.au-access_log" DirData="/var/lib/awstats/pynotes.bjdean.id.au" The configuration follows a simple pattern: include the global settings, then override site-specific values. AWStats expects to find config files named awstats.HOSTNAME.conf in /etc/awstats/. ...

Artificial Intelligence : Masking Sensitive Data

I’ll step away from data analytics for a moment in this series of posts on GenAI to think about Data Masking. As I commented in Artificial Intelligence ? OpenAI ? Data Use and Privacy - there are provacy and security concerns when sending sensitive data to an external provider (in this case a GenAI provider) and where the data structure and volume is small enough one option is Masking. I’ll write another post about applying masking in data analytics - but to step through the process incrementally it’s instructive to think about masking within a single written document as it helps to identify what sort of masking is possible (and what isn’t) and how to apply it. ...

Artificial Intelligence : OpenAI - Analytics, Open Data and A Few Simple Prompts

As I mentioned in my Artificial Intelligence : OpenAI : Data Use and Privacy post, a key consideration when feeding data and dialogue to a third-party GenAI provider like OpenAI’s ChatGPT relates to data privacy. While investigating what you can do with to toolset, or simply if the data you need is available with an open license an excellent way to start is to use Open Data. It’s worth noting that just because data is found in a public location does not mean that it is Open Data. Before using the data in this way make sure to check the publishers license. A good source of open data is public government data - for example as published on sites like: ...

Artificial Intelligence - OpenAI - Data Use and Privacy

This begins a series of articles / code-snippets / thoughts regarding use of Generative Artificial Intelligence (GenAI) for data analytics - starting out primarily using OpenAI. This is not a broader discussion of uses of GenAI (though they’re kinda fun as well, and I’ll probably write about chat and API -style usage in the future). In particular I’m looking at OpenAI’s ChatGPT Plus which (as of the date of writing) is the paid subscription option of ChatGPT which allows access to additional functionality: ...

Migrating git to svn (subversion)

I’ve found that most documentation / forum discussion around the web for this topic tends to be about migrating svn to git - so here’s a quick shell script (reconfigure the variables at the start) to help migrate from git to subversion. This script is also available here: migrate-git-to-svn.sh.txt #!/bin/bash # Run this script from an empty working directory - it will: # 1. git clone from the ORIGIN_GIT URL # 2. run through a number of stages to construct a local svn repository # 3. check out the svn repo for you to check # # NO error checking is done - you need to look at the output and # look for any issues. This script DOES delete it's working directories # on each run (so make sure to start in an empty directory to be safe!) # Configuration PROJECT_NAME=<strong>MyProjectName</strong> ORIGIN_GIT="git@github.com:<strong>UserName</strong>/<strong>MyProjectName</strong>.git" # Keep track of starting directory to make working in sub-directories easier BASEDIR=$PWD # Clone (bare) to main repo from main git repo # Base because later stages want to talk only to a bare repo echo "### Cloning git origin into local bare repo: ${PROJECT_NAME}.git" if [ -d "${PROJECT_NAME}.git" ] ; then rm -rf "${PROJECT_NAME}.git" ; fi git clone --bare "${ORIGIN_GIT}" # Protect the real origin by removing it as a remote in the bare clone echo "### Protect real origin by removing it as a remote in our clone" ( cd "${PROJECT_NAME}.git"; \ git remote remove origin; \ ) # Create an empty svn repository to migrate into echo "### Create and initialise the target svn repository for the migration: ${PROJECT_NAME}.svnrepo" if [ -d "${PROJECT_NAME}.svnrepo" ] ; then rm -rf "${PROJECT_NAME}.svnrepo" ; fi mkdir "${PROJECT_NAME}.svnrepo" svnadmin create "${PROJECT_NAME}.svnrepo" svn mkdir --parents "file://${BASEDIR}/${PROJECT_NAME}.svnrepo/${PROJECT_NAME}/"{trunk,branches,tags} -m 'Inititalise empty svn repo' # git svn (NOTE svn mode - needs the git-svn package installed on debian) # Clone the new local svn repository into a git repo # The --stdlayout option tells "git svn" that we are using the "standard" {trunk,branches,tags} directories echo "### git-svn clone the target svn repo as a git directory (used to import from git and then export to svn): ${PROJECT_NAME}-git2svn" if [ -d "${PROJECT_NAME}-git2svn" ] ; then rm -rf "${PROJECT_NAME}-git2svn" ; fi git svn clone "file://${BASEDIR}/${PROJECT_NAME}.svnrepo/${PROJECT_NAME}" --stdlayout "${PROJECT_NAME}-git2svn" # Set up the bare git clone as the origin for the "${PROJECT_NAME}-git2svn" clone echo "### Add our git clone as the remote origin for ${PROJECT_NAME}-git2svn" ( cd "${PROJECT_NAME}-git2svn"; \ git remote add origin "file://${BASEDIR}/${PROJECT_NAME}.git"; \ ) # Import changes into an import branch in the "${PROJECT_NAME}-git2svn" clone and then export to svn # Note: # 1. git fetch first to get branch details # 2. Then branch to an import branch tracking the remote origin/main # 3. Rebase that onto master (rebase --root commits all reachable, allows to rebase the root commits) # This builds the information needed to sync to svn via dcommit. # 4. Then use svn dcommit - include author information (to help track who made changes) echo "### Import full commit history into ${PROJECT_NAME}-git2svn and then send to subversion repo" ( cd "${PROJECT_NAME}-git2svn"; \ git fetch origin; \ git checkout -b import origin/main; \ git rebase --onto master --root; \ git svn dcommit --add-author-from ; \ ) # Checkout a svn working dir to check the export echo "### Checking out a working svn directory to check the results: svn-check" if [ -d svn-check ] ; then rm -rf svn-check ; fi svn co "file://${BASEDIR}/${PROJECT_NAME}.svnrepo/${PROJECT_NAME}" svn-check echo "Check the contents/log in svn-check/"

qemu - simplest command-line for a performant VM

TL;DR You need to tell qemu to: use the local host CPU (rather than emulating one) and enable hypervisor mode, include a couple of CPU cores for performance, give it a hard disk and some memory and finally (after setting up a bridge network device on your host system) use a bridged network with a MAC address unique to your network. The final bit about networking requires root access - hence the sudo: ...

June 14, 2023 · 3 min · 545 words · Brad