{
    "type": "tag",
    "title": "Python",
    "canonical": "https://www.dealmobile.co.uk/writing/tag/python",
    "path": "/writing/tag/python",
    "url": "https://www.dealmobile.co.uk/writing/tag/python",
    "markdown": "https://www.dealmobile.co.uk/writing/tag/python.md",
    "json": "https://www.dealmobile.co.uk/writing/tag/python.json",
    "feed": "https://www.dealmobile.co.uk/writing/tag/python.rss",
    "items": [
        {
            "type": "article",
            "title": "Safe by default: a local AI server and a cheap model with a shell",
            "url": "https://www.dealmobile.co.uk/writing/safe-by-default-a-local-ai-server-and-a-cheap-model-with-a-shell",
            "markdown": "https://www.dealmobile.co.uk/writing/safe-by-default-a-local-ai-server-and-a-cheap-model-with-a-shell.md",
            "json": "https://www.dealmobile.co.uk/writing/safe-by-default-a-local-ai-server-and-a-cheap-model-with-a-shell.json",
            "summary": "A hardening pass on Mullet: a local server that a web page could not be stopped from calling, tools that fetched any address, and cheap models with more tools than they needed. What each guard checks and where to change it.",
            "published": "2026-10-25"
        },
        {
            "type": "article",
            "title": "Every session starts with one question: what’s the budget?",
            "url": "https://www.dealmobile.co.uk/writing/every-session-starts-with-one-question",
            "markdown": "https://www.dealmobile.co.uk/writing/every-session-starts-with-one-question.md",
            "json": "https://www.dealmobile.co.uk/writing/every-session-starts-with-one-question.json",
            "summary": "A Claude Code hook opens each session by asking how much to spend and how much to delegate to cheaper models, then makes Mullet’s jobs follow the answer.",
            "published": "2026-10-25"
        },
        {
            "type": "article",
            "title": "Mullet is free for your company",
            "url": "https://www.dealmobile.co.uk/writing/mullet-is-free-for-your-company",
            "markdown": "https://www.dealmobile.co.uk/writing/mullet-is-free-for-your-company.md",
            "json": "https://www.dealmobile.co.uk/writing/mullet-is-free-for-your-company.json",
            "summary": "Mullet’s licence used to say one developer, one running instance. It now allows free production use for any purpose, including inside a company, with one exclusion: offering Mullet to others as a service.",
            "published": "2026-10-25"
        },
        {
            "type": "article",
            "title": "We checked the bill, and our ledger was wrong by half",
            "url": "https://www.dealmobile.co.uk/writing/we-checked-the-bill-and-our-ledger-was-wrong-by-half",
            "markdown": "https://www.dealmobile.co.uk/writing/we-checked-the-bill-and-our-ledger-was-wrong-by-half.md",
            "json": "https://www.dealmobile.co.uk/writing/we-checked-the-bill-and-our-ledger-was-wrong-by-half.json",
            "summary": "Mullet’s ledger said about $38 for a weekend of jobs. The providers billed about $50. How I found the gap, why one OpenRouter model was recorded at about a third of its cost, and the checks that now catch it.",
            "published": "2026-10-25"
        },
        {
            "type": "article",
            "title": "Why Mullet doesn’t use FreeLLMAPI",
            "url": "https://www.dealmobile.co.uk/writing/why-mullet-doesnt-use-freellmapi",
            "markdown": "https://www.dealmobile.co.uk/writing/why-mullet-doesnt-use-freellmapi.md",
            "json": "https://www.dealmobile.co.uk/writing/why-mullet-doesnt-use-freellmapi.json",
            "summary": "FreeLLMAPI puts dozens of free LLM tiers behind one endpoint, and it is a good tool for what it says it is for. Mullet 2 needs to know which model did each step and whose terms apply to my code, so it uses one named OpenRouter free model, for public repos only, instead. That rung hasn’t run yet.",
            "published": "2026-10-25"
        },
        {
            "type": "article",
            "title": "The delegation ladder, or who does each step",
            "url": "https://www.dealmobile.co.uk/writing/the-delegation-ladder",
            "markdown": "https://www.dealmobile.co.uk/writing/the-delegation-ladder.md",
            "json": "https://www.dealmobile.co.uk/writing/the-delegation-ladder.json",
            "summary": "How Mullet 2 hands each step of a coding job to the cheapest worker that can pass its checks: free and local models first, then Kimi and OpenRouter, Claude last, with the order set by how much of my Claude week is left.",
            "published": "2026-10-25"
        },
        {
            "type": "article",
            "title": "A 30-minute test suite in five minutes",
            "url": "https://www.dealmobile.co.uk/writing/a-30-minute-test-suite-in-five",
            "markdown": "https://www.dealmobile.co.uk/writing/a-30-minute-test-suite-in-five.md",
            "json": "https://www.dealmobile.co.uk/writing/a-30-minute-test-suite-in-five.json",
            "summary": "Cutting every test off from the real world let Mullet’s tests (about 17,700 when I wrote this) run in parallel, and flushed out a real Kimi call and a fixture deleting a real file.",
            "published": "2026-10-25"
        },
        {
            "type": "article",
            "title": "Running your own Claude subscription unattended",
            "url": "https://www.dealmobile.co.uk/writing/running-your-own-claude-subscription-unattended",
            "markdown": "https://www.dealmobile.co.uk/writing/running-your-own-claude-subscription-unattended.md",
            "json": "https://www.dealmobile.co.uk/writing/running-your-own-claude-subscription-unattended.json",
            "summary": "Mullet 2 drives your own claude -p, touches no credentials, pauses at usage limits, and reads usage from the statusline. Plus an API key trap worth knowing.",
            "published": "2026-10-25"
        },
        {
            "type": "article",
            "title": "Sandboxing an AI coding worker",
            "url": "https://www.dealmobile.co.uk/writing/sandboxing-an-ai-coding-worker",
            "markdown": "https://www.dealmobile.co.uk/writing/sandboxing-an-ai-coding-worker.md",
            "json": "https://www.dealmobile.co.uk/writing/sandboxing-an-ai-coding-worker.json",
            "summary": "How Mullet 2 keeps a coding worker in a private clone behind bubblewrap, and what probing the real Claude Code binary turned up that the docs did not.",
            "published": "2026-10-25"
        },
        {
            "type": "article",
            "title": "Gates, not a model’s word",
            "url": "https://www.dealmobile.co.uk/writing/gates-not-a-models-word",
            "markdown": "https://www.dealmobile.co.uk/writing/gates-not-a-models-word.md",
            "json": "https://www.dealmobile.co.uk/writing/gates-not-a-models-word.json",
            "summary": "How Mullet 2 decides a coding step is done: eight gates that read the diff and the test results, and a reviewer that can block a step but never pass one.",
            "published": "2026-10-25"
        },
        {
            "type": "article",
            "title": "Mullet 2, coding jobs you can leave running",
            "url": "https://www.dealmobile.co.uk/writing/mullet-2-coding-jobs-you-can-leave-running",
            "markdown": "https://www.dealmobile.co.uk/writing/mullet-2-coding-jobs-you-can-leave-running.md",
            "json": "https://www.dealmobile.co.uk/writing/mullet-2-coding-jobs-you-can-leave-running.json",
            "summary": "Mullet 2 plans a coding job, runs it unattended in a sandboxed clone, and passes each step only on evidence. Why I rebuilt it, and how to try it.",
            "published": "2026-10-25"
        },
        {
            "type": "article",
            "title": "A TV remote from the command line",
            "url": "https://www.dealmobile.co.uk/writing/a-tv-remote-from-the-command-line",
            "markdown": "https://www.dealmobile.co.uk/writing/a-tv-remote-from-the-command-line.md",
            "json": "https://www.dealmobile.co.uk/writing/a-tv-remote-from-the-command-line.json",
            "summary": "Pairing a Linux computer with a Google TV over the protocol phone remotes use, what the six-character code on the screen really checks, and why a remote that can’t change anything is worth having next to ADB.",
            "published": "2026-10-23"
        },
        {
            "type": "article",
            "title": "Turning saved web pages into clean Markdown",
            "url": "https://www.dealmobile.co.uk/writing/turning-web-pages-into-clean-markdown",
            "markdown": "https://www.dealmobile.co.uk/writing/turning-web-pages-into-clean-markdown.md",
            "json": "https://www.dealmobile.co.uk/writing/turning-web-pages-into-clean-markdown.json",
            "summary": "How ScrapePy finds the article inside a saved page, strips the menus, adverts and sign-up boxes around it, and points its links at the other Markdown files.",
            "published": "2026-10-21"
        },
        {
            "type": "article",
            "title": "Picking the cheapest model that can do the job",
            "url": "https://www.dealmobile.co.uk/writing/picking-the-cheapest-model-that-can-do-the-job",
            "markdown": "https://www.dealmobile.co.uk/writing/picking-the-cheapest-model-that-can-do-the-job.md",
            "json": "https://www.dealmobile.co.uk/writing/picking-the-cheapest-model-that-can-do-the-job.json",
            "summary": "How Mullet sizes up a task, picks the cheapest model that clears a quality floor for it, and carries on when OpenRouter withdraws a model without notice.",
            "published": "2026-10-21"
        },
        {
            "type": "article",
            "title": "Indexing code by function, class and method",
            "url": "https://www.dealmobile.co.uk/writing/indexing-code-by-function-class-and-method",
            "markdown": "https://www.dealmobile.co.uk/writing/indexing-code-by-function-class-and-method.md",
            "json": "https://www.dealmobile.co.uk/writing/indexing-code-by-function-class-and-method.json",
            "summary": "How Trove splits source code into functions, classes and methods with tree-sitter, re-indexes only the files that changed, and where its extractors fall short.",
            "published": "2026-10-21"
        },
        {
            "type": "article",
            "title": "Finding the dull parts of a screen recording",
            "url": "https://www.dealmobile.co.uk/writing/finding-the-dull-parts-of-a-screen-recording",
            "markdown": "https://www.dealmobile.co.uk/writing/finding-the-dull-parts-of-a-screen-recording.md",
            "json": "https://www.dealmobile.co.uk/writing/finding-the-dull-parts-of-a-screen-recording.json",
            "summary": "How Reelify scores each frame of a screen recording by how much it changed, turns the scores into cuts with a margin around them, works out a speed to fit a target length and cuts out each segment, checked against a test clip with known content.",
            "published": "2026-10-21"
        },
        {
            "type": "article",
            "title": "Cloning every repository without a token in the URL",
            "url": "https://www.dealmobile.co.uk/writing/cloning-repositories-without-a-token-in-the-url",
            "markdown": "https://www.dealmobile.co.uk/writing/cloning-repositories-without-a-token-in-the-url.md",
            "json": "https://www.dealmobile.co.uk/writing/cloning-repositories-without-a-token-in-the-url.json",
            "summary": "How GitHub Auditor keeps a clone of every repository up to date, gives git its token through a short-lived GIT_ASKPASS script instead of the URL, and reports force pushes, dirty clones and deleted repositories.",
            "published": "2026-10-21"
        },
        {
            "type": "article",
            "title": "Counting developer activity from git",
            "url": "https://www.dealmobile.co.uk/writing/counting-developer-activity-from-git",
            "markdown": "https://www.dealmobile.co.uk/writing/counting-developer-activity-from-git.md",
            "json": "https://www.dealmobile.co.uk/writing/counting-developer-activity-from-git.json",
            "summary": "How GitHub Auditor counts commits, lines and reviews across many repositories without counting the same work twice, counting lines nobody wrote, or passing off missing data as a quiet week.",
            "published": "2026-10-20"
        },
        {
            "type": "article",
            "title": "Combining keyword and vector search in Trove",
            "url": "https://www.dealmobile.co.uk/writing/combining-keyword-and-vector-search",
            "markdown": "https://www.dealmobile.co.uk/writing/combining-keyword-and-vector-search.md",
            "json": "https://www.dealmobile.co.uk/writing/combining-keyword-and-vector-search.json",
            "summary": "How Trove runs BM25 and vector search side by side, puts their scores on one scale, and lets a cross-encoder decide the final order, with an example of the reranker overruling both.",
            "published": "2026-10-20"
        },
        {
            "type": "article",
            "title": "Checking a delegate’s edits before trusting them",
            "url": "https://www.dealmobile.co.uk/writing/checking-a-delegates-edits",
            "markdown": "https://www.dealmobile.co.uk/writing/checking-a-delegates-edits.md",
            "json": "https://www.dealmobile.co.uk/writing/checking-a-delegates-edits.json",
            "summary": "How Mullet decides what a cheaper model actually changed, and flags the edits worth a second look, without asking another model and without trusting the first one’s word.",
            "published": "2026-10-20"
        },
        {
            "type": "article",
            "title": "Saving websites for offline reading with ScrapePy",
            "url": "https://www.dealmobile.co.uk/writing/saving-websites-for-offline-reading",
            "markdown": "https://www.dealmobile.co.uk/writing/saving-websites-for-offline-reading.md",
            "json": "https://www.dealmobile.co.uk/writing/saving-websites-for-offline-reading.json",
            "summary": "What it takes to turn a live website into a copy that works with no connection, and how ScrapePy maps URLs to files, rewrites links and only re-downloads what has changed.",
            "published": "2026-10-19"
        }
    ]
}