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. ...

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. ...

A quick start for Python decorators

Synopsis #!/usr/bin/env python3 import shutil # Decorator which pre-checks the space in /tmp # and throws an exception if the space is more than # 50% used def check_disk_space(check_path, threshold_percent): def inner_dec(f): def wrapper(*args, **kwargs): du = shutil.disk_usage(check_path) used_pct = (du.used / du.total) * 100 if used_pct >= threshold_percent: raise Exception(f"Aborting call - {check_path} is >{threshold_percent} (={used_pct}) full") return f(*args, **kwargs) return wrapper return inner_dec # Build another pre-set decorator def check_tmp_over_50(f): return check_disk_space("/tmp", 50)(f) # Use the decorator on some function that # might need /tmp space @check_disk_space('/tmp', 50) def foo(a, b, c): print("Able to run foo - must have been disk space") @check_tmp_over_50 def bar(a, b, c): print("Able to run bar - must have been disk space") if __name__ == '__main__': try: foo(1,2,3) bar(1,2,3) except Exception as e: print(f'foo aborted with: {e}') Getting Started Decorator syntax and usage isn’t all that complicated - but at the moment you won’t find any help from the Python Tutorial (decorators aren’t mentioned in Defining Functions, nor in More on Defining Functions) and the Python Language Reference only really touches on the existence of decorators without much in the way of a detailed description in the Function definitions and Class definitions sections. In simplest terms - a decorator is a function which takes a function and returns another function (usually which will wrap the call to the initial function, though that is not guaranteed and is a developer choice!). The Synopsis above demonstrates the two main patterns: ...

PyCon(line) AU 2020 Rube Codeberg competition

This is for fun, for silliness and for do not use anywhere-ness - or to quote the instructions: If you’ve ever wondered just how egregious your use of Python could be, or how unnecessarily elaborately you could engineer a simple piece of code, we want your entries in our Rube Codeberg competition! Named for the famously complicated machines drawn by American cartoonist Rube Goldberg, the Codeberg competition is a chance for you to showcase your creativity. Everyone is welcome to participate in the competition - or just tune in as the results are announced. You may find you learn a thing or two about how Python ticks along the way. ...

pip - Cannot fetch index base URL http://pypi.python.org/simple/

You want to use pip to install a module from PyPI. However your server distribution in a little old (at the time of writing this did not need to be all that old, so the problem has come up for me a number of times): example@localhost:~/piptest$ pip install mkdocs Downloading/unpacking mkdocs Cannot fetch index base URL http://pypi.python.org/simple/ Could not find any downloads that satisfy the requirement mkdocs No distributions at all found for mkdocs Storing complete log in /home/example/.pip/pip.log A first but not great fix is to simply override the install prefix using: ...

Generating pi (π) using random numbers

I was entertained by Numberphile’s dice-based generation of an approximate of pi so thought I’d throw together a quick script to try this out: random_vals_pi The results look pretty good: $ for x in 1 2 3 4 5 ; do python random_vals_pi.py 100000000 100000; done 3.14130098162 3.13774230925 3.14174020697 3.13769082316 3.14274853819 The theory is based on having large integers, so reducing this reduces the accuracy of the approximation: $ for x in 1 2 3 4 5 ; do python random_vals_pi.py 10 100000; done 3.07962120525 3.0938112197 3.08601801522 3.08910857173 3.08599352408 And similarly reducing the number of samples does the same: ...