# Daniel John Morris > Daniel John Morris - Technology Director at Cubitts. I build with LLMs and AI agents, and I created ilo-lang, a token-minimal programming language for AI agents. 18+ years in tech leadership. Technology Director at Cubitts. I build with LLMs and AI agents, and I created ilo-lang, a token-minimal programming language for AI agents. 18+ years in the digital industry, 13 years in tech leadership. This file follows the [llms.txt](https://llmstxt.org) convention. Full content is at [/llms-full.txt](https://danieljohnmorris.com/llms-full.txt). ## About - [Home](https://danieljohnmorris.com/): landing page with featured work and recent writing - [Journey](https://danieljohnmorris.com/journey/): career timeline - [Projects](https://danieljohnmorris.com/projects/): case studies - [Writing](https://danieljohnmorris.com/writing/): articles and notes - [Reading](https://danieljohnmorris.com/reading/): books and references - [Setup](https://danieljohnmorris.com/uses/): tools, stack, environment - [Contact](https://danieljohnmorris.com/contact/): how to get in touch ## Writing - [Three Ways to Wire Two Services on AWS](https://danieljohnmorris.com/writing/three-ways-to-wire-two-services-on-aws/): A shop and a pharmacy, wired three ways: NAT gateways and IP allowlists, queues between VPCs, IAM identity instead of addresses. Same code, different security. - [floci: Which Parts of AWS Run Locally for Real](https://danieljohnmorris.com/writing/floci-local-aws-what-runs-for-real/): I put floci, a LocalStack replacement, through the services a two-VPC design needs. Lambda, ECS, RDS and SQS run. WAF and API Gateway AWS_IAM enforce nothing. - [Shipping Headlong's Design Doc: The Memory Ladder in ai-coworkers](https://danieljohnmorris.com/writing/headlong-memory-ladder-shipped/): Laude published a progressive-resolution memory design and marked it unimplemented. This is what it looks like shipped in another runtime, and what I refused to take. - [Reverse-Engineering omp.sh's Dithered Background](https://danieljohnmorris.com/writing/reverse-engineering-dithered-background/): How omp.sh draws its pink dithered planet with a 2D canvas and no WebGL, worked out from the minified bundle and rebuilt as five variations. - [Self-hosting a Linear or Jira Replacement: Plane and Huly on 8 GB](https://danieljohnmorris.com/writing/self-hosting-a-linear-or-jira-replacement/): The two open-source issue trackers worth running in place of Linear or Jira. Huly's own README asks for 8 GB minimum, and the box had 3.6 GB free. - [Simple custom website blocker for Chrome](https://danieljohnmorris.com/writing/simple-custom-website-blocker/): A Chrome extension that blocks sites for eight hours, a day, a week, or permanently, with no way to lift a block early from the popup. - [Building with vgpu, Vercel's WebGPU Library](https://danieljohnmorris.com/writing/building-with-vgpu/): I pulled four shader demos out of vgpu's example gallery and shipped them as live sites. One of them took five rounds of debugging to run smoothly. - [Comparing graft and jCodeMunch](https://danieljohnmorris.com/writing/comparing-graft-and-jcodemunch/): Two MCP servers that index a repo with tree-sitter. I measured both on the same code: 886 tokens of tool schema against 27,526. - [Headlong vs ai-coworkers: What Should an Agent Do When Nothing Is Happening?](https://danieljohnmorris.com/writing/headlong-vs-ai-coworkers-idle/): Laude's Headlong thinks continuously and costs $1-2 an hour at idle. My runtime returns before the model is called. One design question separates them. - [Self-Hosting cal.diy on an arm64 Box](https://danieljohnmorris.com/writing/self-hosting-cal-diy-on-arm64/): The image its README advertises has zero tags. Building it took nine minutes and shipping it would have taken two hours, so the build moved to CI. - [Referencing a skill instead of installing it](https://danieljohnmorris.com/writing/referencing-a-skill-instead-of-installing-it/): A paper argues installed skills spend a scarce prompt budget. I measured mine at 2,225 resident tokens, then ran the @skills reference client. - [Where Agent Behaviour Lives: dsh, Claude Code and pi](https://danieljohnmorris.com/writing/where-agent-behaviour-lives-dsh-claude-code-pi/): DeepSeek's dsh keeps its hardcoded prompt to one sentence. Claude Code puts orchestration in prose. pi hands the choice to you. I read the source of all three. - [Four Places to Catch a Model's Mistake](https://danieljohnmorris.com/writing/four-places-to-catch-a-models-mistake/): BAML repairs the output, Hyperlambda gates the execution, Zero explains the failure, ilo shrinks the surface. Four languages for agents, four different moments to intervene. - [Why Every Model Lab Ships a Harness](https://danieljohnmorris.com/writing/why-model-labs-ship-harnesses/): DeepSeek just released dsh, its own coding agent. That makes four labs with harnesses. The reasons are distribution, training data and benchmark control. - [65% and 8.5% Are the Same Tool](https://danieljohnmorris.com/writing/65-percent-and-8-percent-same-tool/): I wrote a command to audit projects from primary sources, ran it on caveman and BAML, and found my own documentation quoting a savings figure the vendor had already withdrawn. - [The Same Two Commits in git, jj, and atomic](https://danieljohnmorris.com/writing/same-two-commits-git-jj-atomic/): I made the same conflicting pair of changes in three version control systems. git blocked, jj carried on, atomic merged them without a conflict at all. - [Microsoft's agent governance toolkit](https://danieljohnmorris.com/writing/microsoft-agent-governance-toolkit/): Microsoft published an agent governance toolkit in March. I cloned the Claude Code plugin, read the policy it ships with, and ran that policy against nine commands. - [Most of a system prompt is tool definitions](https://danieljohnmorris.com/writing/most-of-a-system-prompt-is-tool-definitions/): A claimed GPT-5.6 prompt runs 17,124 words. I counted the sections. One of them, the tool namespaces, is 71% of the file. - [Three Things People Call Distillation](https://danieljohnmorris.com/writing/three-things-called-distillation/): The word covers logit matching, synthetic fine-tuning and on-policy grading. Only one needs an open teacher, and the choice decides what a result proves. - [Agent Plugins 1.0 is out](https://danieljohnmorris.com/writing/agent-plugins-1-0/): An open format for packaging agent extensions, backed by Amazon, Cursor, Microsoft, OpenAI and Vercel. Here is what is in it. - [OpenSRE: The First Agent Framework With a Job Title](https://danieljohnmorris.com/writing/opensre-the-domain-shaped-agent/): Tracer Cloud's incident-response agent bakes the role into the code instead of the prompt. How it compares to the general-purpose frameworks and to ai-coworkers. - [Self-hosting Analytics Behind Cloudflare Access](https://danieljohnmorris.com/writing/self-hosting-analytics-behind-cloudflare-access/): Moving off Umami Cloud onto a VPS that was already running, with Cloudflare Access in front of the dashboard. The parts that did not work first time. - [Buzz Gives Agents Keypairs](https://danieljohnmorris.com/writing/buzz-agents-with-keypairs/): Block's workspace makes agents sign every action into an auditable chain. A close look at the architecture, what is real today, and what it means for accountable agents. - [Hermes Is Now the Most-Starred Agent on GitHub](https://danieljohnmorris.com/writing/hermes-most-starred-agent/): 222.6k stars and rank #20 all time for a memory-first assistant. Why the learning loop beat the gateway, and what sits at #19 right next to it. - [Everyone Built the Agent Language at the Same Time](https://danieljohnmorris.com/writing/everyone-built-the-agent-language-at-once/): I measured commit activity across all 31 catalogued agent languages. Two camps are alive, one is empty, and half the field reached for the definite article. - [Eve, From the Ship London Launch to Production Agents](https://danieljohnmorris.com/writing/eve-at-vercel-ship-london/): I was in the room when Vercel launched Eve, and I have since run Eve agents at work. Where the agents-as-directories idea holds up and where the platform lock-in bites. - [The Orchestrator's Tax, Paid From My Own Pipeline](https://danieljohnmorris.com/writing/orchestrator-tax-own-pipeline/): Rahul Garg's martinfowler.com piece names the real cost of subagents: what they leave in the orchestrator's context. My persona and fix pipeline hit the same walls. - [mattpocock/skills v1.2: One Skill Set, Every Agent](https://danieljohnmorris.com/writing/mattpocock-skills-v1-2/): 204k stars and 13.5m installs later, Matt Pocock's skills repo shows what agent behaviour distribution looks like when it is just markdown files and an installer. - [Next.js 16.3: The Agent Features Are the Story](https://danieljohnmorris.com/writing/nextjs-16-3-agent-features/): The 16.3 release notes split three ways and one whole strand is for AI agents: bundled AGENTS.md docs, first-party skills, browser introspection, a slimmer MCP server. - [The Agent Client Protocol, From Zed to Buzz](https://danieljohnmorris.com/writing/agent-client-protocol-zed-to-buzz/): 25+ agents, a registry with JetBrains, and now Buzz using it to admit agents as teammates. What I found reading the ACP spec, and where it fits next to MCP. - [ai-coworkers: Fusing Six Agent Frameworks and Keeping Their Plugins](https://danieljohnmorris.com/writing/fusing-six-frameworks-into-ai-coworkers/): What I took from OpenClaw, Hermes, ElizaOS, Eve, and the memory papers, what had to be built new, and how existing skills and MCP servers plug straight in. - [Why No Existing Agent Framework Gives You an AI Coworker](https://danieljohnmorris.com/writing/no-agent-framework-is-a-coworker/): I surveyed OpenClaw, NanoClaw, Hermes, ElizaOS, Vercel Eve, and Block's Buzz looking for a long-running coworker with a role. The gap is the same in all six. - [MCP Goes Stateless](https://danieljohnmorris.com/writing/mcp-goes-stateless/): The 2026-07-28 spec removes the handshake and sessions, making any MCP request routable to any server instance. What changed and what it means for server authors. - [Error Output Is an Agent Interface](https://danieljohnmorris.com/writing/error-output-is-agent-interface/): One malformed ilo run produced a 42,000-token error message. For a language agents write, error output is not diagnostics, it is the retry prompt. - [Your Spec Is the Product: ilo's 44k-Token Problem](https://danieljohnmorris.com/writing/spec-budgets-for-agent-languages/): For an agent language, the spec is what the model reads before writing a line. Mog capped theirs at 3,200 tokens. ilo's has grown past 40,000. One of us is wrong. - [agentlanguages.dev and the Three Camps](https://danieljohnmorris.com/writing/agentlanguages-dev-three-camps/): Someone finally catalogued the languages designed for AI agents to write. The camp structure is the useful part, and ilo is not on the map yet. - [Self-hosting DMARC Reports and Status Pages](https://danieljohnmorris.com/writing/self-hosting-dmarc-reports-and-status-pages/): Two jobs with good paid products behind them. What parsedmarc and dmarc-srg cost in memory, what Statuspage and Better Stack cost in money, and why Upptime is running twice. - [How SPF and DKIM Became DMARC](https://danieljohnmorris.com/writing/how-spf-and-dkim-became-dmarc/): SPF checks an address the reader never sees and DKIM signs a domain they never read. DMARC is the record that ties both to the From line, and the one that finally reports back. - [Model Routers, and the Routing I Already Do by Hand](https://danieljohnmorris.com/writing/model-routers/): Every multi-agent pipeline is already a model router with a human in the routing table. What the automated routers do, and what my own tier assignments taught me. - [Build Your Own Git in 88 Lines](https://danieljohnmorris.com/writing/build-your-own-git-88-lines/): Enough of git that the real git log, cat-file, and fsck accept the output: init, blobs, trees, commits, and a log walker, in 88 lines of Python. - [Where Agent Skills Come From](https://danieljohnmorris.com/writing/where-agent-skills-come-from/): Registries, curated directories, and host marketplaces all distribute the same markdown files. A map of the three shapes and what each one adds. - [RTK: reducing token usage in LLM workflows](https://danieljohnmorris.com/writing/rtk-token-compression/): A CLI proxy that compresses command output before it reaches your LLM context. 60-90% savings on git, cargo, and test output. Built in Rust with zero dependencies. - [An A/B Against the Manifesto](https://danieljohnmorris.com/writing/agent-natural-ab-against-the-manifesto/): ilo's manifesto says prefix beats infix on tokens. The persona logs suggest infix beats prefix on retries. So I built an A/B to settle it. - [Open Source Workflow Automation for ilo-lang](https://danieljohnmorris.com/writing/ilo-lang-workflows/): The four scripts that handle version bumps, releases, site deploys, and branch sync for ilo-lang - one command or one tag push for each. - [What is a Recursive Language Model](https://danieljohnmorris.com/writing/what-is-a-recursive-language-model/): Recursive Language Models offload large contexts into a sandboxed Python variable and let the model write code to navigate. I tested DSPy's implementation on fastapi, vite, and the full VS Code source against naive prompting to see where the wins are. - [Tier 3 logging in code: OpenTelemetry to Grafana Tempo](https://danieljohnmorris.com/writing/tier-3-logging-in-code/): The three changes that take a serverless API from Powertools and traceparent strings to OTel SDK spans shipping to Tempo, with a runnable docker-compose stack. - [Tier 2 logging in code: Powertools, EMF, traceparent](https://danieljohnmorris.com/writing/tier-2-logging-in-code/): The three changes that take a serverless API from CloudWatch-only logging to Tier 2, walked through with a runnable LocalStack repo and the actual log lines it produces. - [API logging in production](https://danieljohnmorris.com/writing/api-logging-in-production/): Three-tier guide to logging a serverless API on AWS. The CloudWatch-only baseline in detail, plus what I would reach for next when it strains. - [How AI agents find code in your repo](https://danieljohnmorris.com/writing/codebase-indexing-strategies-may-2026/): Agents read too much code. Five strategies they use to fix it, from raw file reads to recursive language models. - [DynamoDB single-table design, worked through](https://danieljohnmorris.com/writing/dynamodb-single-table-design/): Four entities, six access patterns, one table, one GSI. The key design walked step by step with the runnable repo behind it. - [Orchestration vs choreography: which to choose](https://danieljohnmorris.com/writing/orchestration-vs-choreography/): Side by side comparison of the two saga implementations from the previous posts. What each one cost to build, what it gives you operationally, and which questions to ask before picking. - [Orchestration with Step Functions](https://danieljohnmorris.com/writing/orchestration-with-step-functions/): The same four-step order saga, this time driven by a Step Functions state machine. Catch blocks for compensation, no event bus. - [Choreography with EventBridge](https://danieljohnmorris.com/writing/choreography-with-eventbridge/): Four Lambdas coordinated through EventBridge events, deployed to LocalStack. The first half of a saga pattern comparison; the orchestration version comes next. - [Low-Poly 3D Clouds in Three.js](https://danieljohnmorris.com/writing/threejs-polygonal-clouds/): How the polygonal cloud background on this site works: a single InstancedMesh, jittered icosahedron geometry, cel-shaded clusters of flat blobs, fog, and mouse parallax. - [Parquet vs CSV file format](https://danieljohnmorris.com/writing/parquet-vs-csv-file-format/): Parquet stores values column-by-column with a metadata footer at the end. CSV stores rows. That layout difference is why analytical tools default to parquet. - [Trying DuckDB With an AI Query Chat](https://danieljohnmorris.com/writing/trying-duckdb-with-ai-query-chat/): Evidence.dev runs on DuckDB-WASM in the browser. I wanted to try DuckDB directly, so I built a chat that asks Claude for SQL and runs it locally. - [Three Bets on Long-Context Attention](https://danieljohnmorris.com/writing/three-bets-on-long-context-attention/): Gemma 4, Qwen 3.6, and DeepSeek V3 each take a different path to long context. A reverse-engineering test shows where the trade hurts. - [Plugging KataGo Into the 5x5 Demo](https://danieljohnmorris.com/writing/5x5-go-vs-katago/): Replacing the 2-ply minimax bot with KataGo. FastAPI subprocess wrapper, Dockerfile pulling the eigenavx2 binary, deploy on a single shared VPS. - [5x5 Go With a Two-Move Lookahead](https://danieljohnmorris.com/writing/5x5-go-against-a-bot/): A playable 5x5 Go board with capture, suicide, ko, and area scoring. The bot evaluates each candidate move after Black's best reply. - [Part 5: Planning in Latent Space](https://danieljohnmorris.com/writing/planning-in-latent-space/): Action-conditioned JEPA on the bouncing ball. Add direction as input to the predictor and the bimodal-future problem disappears. Brute-force MPC in embedding space drives a goal-image rollout. - [Part 4: From Representations to World Models](https://danieljohnmorris.com/writing/from-representations-to-world-models/): Running DINOv2 on a real image to see what a production joint-embedding encoder learns. Click a patch, get a similarity heatmap. No labels, no fine-tuning. - [Cloud queue inbox/outbox patterns](https://danieljohnmorris.com/writing/cloud-queue-inbox-outbox-pattern/): Building outbox/inbox patterns on DynamoDB Local and LocalStack, with a list of queue smells the patterns don't fully cover. - [Part 3: Predict Embeddings, Not Pixels](https://danieljohnmorris.com/writing/predict-embeddings-not-pixels/): Joint embedding training, the representation collapse problem, and how Barlow Twins, VICReg, and LeJEPA's SIGReg fix it. Tested on the same bouncing-ball toy from Part 2. - [Part 2: Why Pixel Prediction Goes Blurry](https://danieljohnmorris.com/writing/why-pixel-prediction-goes-blurry/): Yann LeCun says generative models fail on video because the future is ambiguous. I tested the claim with a 700K-parameter PyTorch model on a synthetic bouncing ball. - [Part 1: Yann LeCun's Bet Against LLMs](https://danieljohnmorris.com/writing/yann-lecun-bet-against-llms/): The LeCun argument in plain terms, with the papers behind it. The map for a five-part series testing his recommendations on a MacBook. - [Decode throughput is bandwidth divided by model size](https://danieljohnmorris.com/writing/decode-throughput-is-bandwidth-divided-by-model-size/): Single-token decode reads every weight once, so the spec sheet predicts tokens per second before you download anything. Measured against six Qwen models on an M3 Max. - [Loading ilo, Part 3: Harness Layer](https://danieljohnmorris.com/writing/loading-ilo-part-3-harness-layer/): Two coding-agent forks (Warp, pi) that bake ilo in at the harness layer instead of loading it as a skill. - [Loading ilo, Part 2: Agent Skill](https://danieljohnmorris.com/writing/loading-ilo-part-2-agent-skill/): Second attempt at loading ilo into the agent loop. Package the spec as an agent skill so it loads only when ilo is relevant. - [Loading ilo, Part 1: System Message](https://danieljohnmorris.com/writing/loading-ilo-part-1-system-message/): First attempt at loading ilo into a real agent loop. Paste the compact spec into the system message and see how far it gets. - [pi vs Claude Code: The Philosophical Split](https://danieljohnmorris.com/writing/pi-vs-claude-code-coding-agent-landscape/): Two TypeScript agents with opposite design choices. A half-million-line spaceship versus a four-tool kit. - [pi: The Minimal Coding Agent](https://danieljohnmorris.com/writing/pi-minimal-coding-agent/): Mario Zechner built pi after souring on every existing coding agent. Two talks worth watching, and what he claims pi does differently. - [Coding Agents in May 2026: A Field Guide](https://danieljohnmorris.com/writing/coding-agents-compared-may-2026/): Claude Code, Codex CLI, opencode, kilocode, pi, plus the commercial tools. What each one is and where the philosophical lines fall. - [The Claude Code Source Leak: What the Dump Shows](https://danieljohnmorris.com/writing/claude-code-source-leak/): A misconfigured package.json field shipped Claude Code's full source to npm. What the half-million lines say about how the tool is built, and what it gives competitors. - [What's New in TypeScript 6.0](https://danieljohnmorris.com/writing/whats-new-in-typescript-6/): TypeScript 6.0 ships stricter defaults, modern compile targets, and clears the path for the Go-native 7.0 release later this year. - [DeepSeek V4 on Apple Silicon: Current Status](https://danieljohnmorris.com/writing/deepseek-v4-on-a-macbook/): What the V4-Pro and V4-Flash checkpoints weigh on disk and in memory, mapped to the unified-memory ceilings of current MacBook Pro and Mac Studio configurations. - [DeepSeek V4: Don't Look at What You Don't Need](https://danieljohnmorris.com/writing/deepseek-v4-dont-look-at-what-you-dont-need/): DeepSeek V4 reads a million tokens on roughly a quarter of V3.2's compute. It does this by selectively attending to the parts of context the prompt asks about, the same way humans skim a long book. - [One Live Search, Five Stacks](https://danieljohnmorris.com/writing/live-search-five-stacks/): The same live-search feature in HTMX, React Server Components, Livewire, Hotwire, and LiveView. Same dataset, same UX, five different ways the server returns HTML instead of JSON. - [HTML Over the Wire: The Fifth Shape of Service Communication](https://danieljohnmorris.com/writing/html-over-the-wire/): RSC, Hotwire, LiveView, Livewire, HTMX. When the server returns rendered HTML and the API disappears. - [Making APIs and Queues Bulletproof](https://danieljohnmorris.com/writing/bulletproof-apis-and-queues/): Idempotency keys, layered caching, transactional outbox/inbox, and DLQs - the patterns that keep money moving when half the systems involved restart in the middle. - [Karpathy's Wiki, OpenBrain, and Picking a Context Layer for AI](https://danieljohnmorris.com/writing/karpathy-wiki-openbrain-context-layer/): Two memory models for AI work. One synthesises on write, one on query. Which to pick depends on whether you're a solo researcher or running multi-agent. - [OpenUISpec and the Case for Telling LLMs What's On the Page](https://danieljohnmorris.com/writing/openuispec-telling-llms-whats-on-the-page/): A spec for AI-readable component libraries. The same idea would cut the cost of scraping the web in half, if anyone published it. - [Types of APIs and Event Queues: When To Use Each](https://danieljohnmorris.com/writing/rest-grpc-trpc-event-queues/): Four ways to move data between services. What each one buys you, where each one falls down, and when I reach for which. - [Wireframe Ocean Waves in Three.js](https://danieljohnmorris.com/writing/threejs-wireframe-waves/): A low-poly wireframe ocean viewed from above. Simplex noise displacement, height-based colouring, and scroll-driven camera in under 350 lines. - [Boids Flocking in Three.js](https://danieljohnmorris.com/writing/threejs-boids-flocking/): 150 low-poly birds with separation, alignment, and cohesion. One HTML file, instanced rendering, vertex shader wing flapping. - [Ghibli-Style Shaders and Frosted Glass in Three.js](https://danieljohnmorris.com/writing/ghibli-shader-parallax-scene/): Cel-shading a procedural mountain scene with discrete brightness bands, edge detection outlines, and mottled frosted glass text panels. - [Six Ways to Give an AI Agent a Map of Your Code](https://danieljohnmorris.com/writing/codebase-graph-tools-vs-ilo-graph/): Prowl, CodeBoarding, Memgraph GraphRAG, CodeGraphContext, SymDex, and jCodeMunch all solve the same problem differently. So does ilo graph. A comparison. - [SudoLang and ilo: Two Opposite Bets on AI Programming](https://danieljohnmorris.com/writing/sudolang-vs-ilo/): SudoLang asks the LLM to interpret pseudocode. ilo gives the LLM a real compiler. Both claim to be AI-first languages. They agree on almost nothing. - [Converting Custom Annotations to YOLO Keypoint Format](https://danieljohnmorris.com/writing/go-board-annotation-to-yolo/): My corner annotator outputs JSON. YOLO wants normalised bounding boxes with keypoints in a specific folder structure. Bridging the two formats. - [Corner Annotation, Board Scraping, and Training YOLO](https://danieljohnmorris.com/writing/go-board-yolo-training/): No off-the-shelf model could find board corners reliably. I built a manual annotator, scraped training data, and trained a YOLO model on the results. - [From Roboflow to SAM 3 on Rented GPUs](https://danieljohnmorris.com/writing/go-board-roboflow-sam/): Classical CV couldn't handle real-world Go board photos. I tried Roboflow, Meta's SAM 3, Ultralytics, Google Colab, and Vast.ai. Each solved one problem and introduced another. - [Isometric Rooms in Three.js](https://danieljohnmorris.com/writing/threejs-isometric-rooms/): Four navigable rooms built from box primitives, arranged in a diamond and rotated with an orthographic camera. One HTML file, no build step. - [Scroll-Driven 3D Parallax With Three.js](https://danieljohnmorris.com/writing/threejs-parallax-mountain-scene/): Building a procedural mountain valley you fly through by scrolling. Two versions, from flat terrain to trees, water, and post-processing. - [Shipping to Four Registries From One Git Tag](https://danieljohnmorris.com/writing/shipping-to-four-registries-from-one-tag/): One tag push builds native binaries, WASM, publishes to crates.io, npm, and GitHub Releases, and updates a Claude Code skill. The full pipeline for ilo. - [Data Pipelines in 50 Tokens](https://danieljohnmorris.com/writing/ilo-data-pipelines/): ilo now handles the full fetch, parse, transform, aggregate, write cycle. The builtins that made it possible. - [Same API in Python, Node, Rust, and Go](https://danieljohnmorris.com/writing/simple-api-across-languages/): The same three-endpoint JSON API built nine ways across Python, Node, Rust, and Go. What each framework gets right and what makes you swear. - [jCodeMunch: Use 80% Less Context](https://danieljohnmorris.com/writing/jcodemunch-mcp-token-savings/): jCodeMunch-MCP uses tree-sitter AST parsing to build a symbol index of your codebase, letting AI agents pull individual functions instead of whole files. The token savings are significant. - [Neon: Branching, Scale-to-Zero, Time Travel](https://danieljohnmorris.com/writing/neon-serverless-postgres/): Branching, scale-to-zero, time travel, schema diff. Neon does things with Postgres that RDS and local containers can't. - [Replacing AWS with Docker Swarm on a VPS](https://danieljohnmorris.com/writing/aws-to-docker-swarm/): I built the same stack twice - once on AWS, once on a Hetzner VPS with Docker Swarm. The VPS version costs less, deploys faster, and has fewer moving parts. - [Animated Fluid Background in Three.js: Simplex Noise and Fragment Shaders](https://danieljohnmorris.com/writing/threejs-fluid-background/): How the animated background on this site works: a fullscreen shader quad, FBM noise, domain warping, per-page colour palettes, and light/dark mode support. - [CNN Regression on Rendered Meshes: What Improved It](https://danieljohnmorris.com/writing/cnn-3d-landmark-regression/): Getting a feature detector from terrible to useful: data leakage, camera projection, horizontal mirroring, memory management, and a second-layer MLP for 3D. - [Getting the most out of Claude Code](https://danieljohnmorris.com/writing/claude-code-workshop-teams/): I ran a half-day Claude Code workshop for a team of technical and non-technical staff. Here's what I covered, what landed, and the habits that stuck. - [Replacing a Raspberry Pi with a Browser Tab](https://danieljohnmorris.com/writing/auto-print-kiosk-mode/): How we replaced a dedicated Raspberry Pi print agent with Chrome's kiosk-printing mode and an existing web app. - [From 1,696ns to 3ns: Five Layers of VM Optimisation](https://danieljohnmorris.com/writing/from-interpreter-to-jit/): The full performance story of ilo's VM. Tree-walker to bytecode to register VM to JIT, with real numbers at each step. - [What If Bash Had Types? ilo as a Shell for AI Agents](https://danieljohnmorris.com/writing/ilo-as-typed-shell/): Unix pipes have lasted 50 years because the model works. ilo takes the same model and adds types. - [Tokenizers Don't Care About Your Abbreviations](https://danieljohnmorris.com/writing/tokenizers-dont-care-about-your-abbreviations/): A short-naming convention for ilo, tested against cl100k_base. The tokenizer already handles common English words in one token. - [Stealing From LuaJIT and V8: What Works in Rust and What Doesn't](https://danieljohnmorris.com/writing/luajit-v8-tricks-in-rust/): I tried to port performance tricks from LuaJIT and V8 to a Rust bytecode VM. Some translated beautifully. Others fought the language at every step. - [The Dot Product Is All You Need](https://danieljohnmorris.com/writing/the-dot-product-is-all-you-need/): Every neural network, every embedding, every attention head reduces to the same operation: multiply and sum. How the dot product encodes meaning in high-dimensional space. - [Cranelift vs LLVM for a Hobby JIT: Why I Chose Cranelift](https://danieljohnmorris.com/writing/cranelift-vs-llvm/): I built the same JIT backend twice - once with Cranelift, once with LLVM via inkwell. Same performance, very different experience. - [Writing a JIT Compiler by Hand on Apple Silicon](https://danieljohnmorris.com/writing/hand-rolled-arm64-jit/): An ARM64 JIT that emits raw machine code, mmaps it executable, and calls it as a function pointer. No LLVM, no Cranelift, just bytes. - [Attention Is All You Need: Building the Original Transformer that Started the LLM Revolution](https://danieljohnmorris.com/writing/attention-is-all-you-need/): Attention Is All You Need replaced RNNs with self-attention and changed everything. I built the original encoder-decoder transformer from scratch and trained it to translate English to French. - [From Stack VM to Register VM: A 31% Speedup by Changing the Model](https://danieljohnmorris.com/writing/stack-vm-to-register-vm/): I rewrote my bytecode VM from stack-based to register-based. The instruction count dropped by 67% and performance improved by 31%. - [Building a Tiny LLM From Scratch, Trained on Poe](https://danieljohnmorris.com/writing/building-a-tiny-llm-from-scratch/): A decoder-only transformer, two tokenizers, and 1.9 million characters of Edgar Allan Poe. What building an LLM from zero teaches you. - [NaN Boxing in Rust: Cramming Every Value Into 8 Bytes](https://danieljohnmorris.com/writing/nan-boxing-in-rust/): LuaJIT packs every value into 8 bytes using NaN boxing. Porting this to Rust means opting out of everything the language gives you. - [--explain: Reading a Language You Don't Know](https://danieljohnmorris.com/writing/ilo-explain-flag/): ilo's annotation tool shows the structural role of every statement. Built for agents, useful for humans too. - [Chaining Transforms with >>](https://danieljohnmorris.com/writing/ilo-pipe-operator/): ilo's pipe operator passes the result of one call into the next. No intermediate names needed. - [Higher-Order Functions Without Lambdas](https://danieljohnmorris.com/writing/ilo-hof-without-lambdas/): ilo added map, flt, and fld - but not anonymous functions. Here's why named functions win for AI agents. - [AI Is Pushing Programming Toward Typed Languages](https://danieljohnmorris.com/writing/ai-pushing-toward-typed-languages/): AI code generation works better with strict type systems and compilers that catch mistakes. The old downsides of compiled languages are starting to matter less. - [Nine Syntax Experiments: What I Learned Testing Language Designs Against LLMs](https://danieljohnmorris.com/writing/nine-syntax-experiments/): Nine syntax variants for the same language, benchmarked against Claude Haiku. Positional args mattered more than abbreviations. - [Guards Instead of if/else](https://danieljohnmorris.com/writing/ilo-guards-not-if-else/): Flat early returns vs nested conditionals. Why ilo ditched if/else entirely. - [Why ilo Has No Mutable Variables](https://danieljohnmorris.com/writing/ilo-no-mutable-variables/): Immutability wasn't an ideological choice. It was a token-cost calculation. - [ViNext: Cloudflare Rebuilt Next.js on Vite in a Week](https://danieljohnmorris.com/writing/cloudflare-vinext-nextjs-on-vite/): Cloudflare's vinext reimplements the Next.js API surface on Vite. What it is, how to migrate, and how to deploy it to both Cloudflare Workers and a VPS. - [Claude Code Agent Teams: Multiple AI Sessions Working Together](https://danieljohnmorris.com/writing/claude-code-agent-teams/): Anthropic shipped agent teams for Claude Code - multiple independent Claude instances that coordinate through shared task lists and direct messaging. Here's how they work, when to use them, and what to watch out for. - [OpenVPN on an EC2 Bastion: Private Network Access Without the Complexity](https://danieljohnmorris.com/writing/openvpn-ec2-bastion/): Setting up OpenVPN on a small EC2 instance as a bastion host for secure access to private AWS resources. No managed VPN service, no over-engineering. - [Vercel's "React Best Practices" Agent Skill launches](https://danieljohnmorris.com/writing/vercel-react-best-practices-agent-skill/): Vercel released 40+ React and Next.js performance rules packaged as an agent skill. It's a structured ruleset that AI coding tools can reference to catch waterfalls, bundle bloat, and unnecessary re-renders. - [Claude Code Custom Commands: Debugging Distributed Systems at Scale](https://danieljohnmorris.com/writing/claude-code-custom-commands/): Using custom Claude Code commands to trace issues through AWS logs, identify root causes in minutes, and audit multi-stage workflows. How I built /check-services and /check-orders. - [Why I'm Building a Programming Language for AI Agents](https://danieljohnmorris.com/writing/why-build-a-language-for-ai/): Every language ever made was designed for humans. What happens when you start from scratch for a different audience? - [Claude Code Workflows: Worktrees and Automated PR Review](https://danieljohnmorris.com/writing/claude-code-workflows/): Part 3 of the AI tooling series. How I use git worktrees for parallel development and a 5-agent automated PR review pipeline inside Claude Code. - [Setting Up an Autonomous AI Agent on a VPS with OpenClaw](https://danieljohnmorris.com/writing/setting-up-openclaw-on-a-vps/): Installing OpenClaw on a Hetzner VPS, connecting Telegram and ProtonMail, and trying to get a model to act without asking permission first. - [Self-Hosting Next.js: OpenNext, AWS, and Running It on Your Own Server](https://danieljohnmorris.com/writing/self-hosting-nextjs-opennext/): Next.js is tightly coupled to Vercel. OpenNext is the project trying to change that, and it now covers most of the hard cases. What it takes to run Next.js yourself. - [Moving This Site Off Vercel: Hetzner, Docker, and Dokploy](https://danieljohnmorris.com/writing/astro-site-from-vercel-to-vps/): Vercel's pricing is fine until it isn't. How I moved my Astro site to a Hetzner VPS with Dokploy and what that setup looks like. - [Why I Switched From Cursor to Claude Code](https://danieljohnmorris.com/writing/claude-code-over-cursor/): After a year with Cursor, I moved to Claude Code's CLI. No IDE lock-in, better context management, and a workflow built around plans and persistent memory. - [SST to CDK: Lessons from Running Multiple Services on AWS](https://danieljohnmorris.com/writing/sst-to-cdk-aws-deployment-lessons/): I ran SST across multiple production services for months, then switched everything to CDK. Here's what broke, what I learned, and the rule I now follow about what never goes in a CDK stack. - [Detecting a Go Board with OpenCV and Hough Circles](https://danieljohnmorris.com/writing/go-board-cv-hough/): I'm building a system that reads a physical Go board from a photo. The first attempt used classical computer vision. It mostly worked. - [The Hidden Cost of Embedding](https://danieljohnmorris.com/writing/the-hidden-cost-of-embedding/): OpenAI's embedding API charges per token across ingestion, re-ingestion, and every query. Switching to a local Ollama model eliminated the recurring cost with comparable retrieval quality. - [Tool-Forced RAG: Stopping the LLM From Making Up Clinical Guidelines](https://danieljohnmorris.com/writing/tool-forced-rag/): LLMs confidently generate plausible clinical advice that doesn't match published standards. Forcing document retrieval for professional questions prevents this. - [Per-Channel vs Per-User: What Memory Model Works for AI Chat](https://danieljohnmorris.com/writing/per-channel-vs-per-user-memory/): Slack conversations are collaborative. Persisting context per channel captures the full picture. Per-user memory misses half the conversation. - [Rewriting a Chat API in Go for Lambda: Cold Starts and Trade-offs](https://danieljohnmorris.com/writing/go-chat-api-lambda/): The Node.js chat API worked but Lambda cold starts were slow and memory usage was high. Go fixed both, but the rewrite taught me more than I expected. - [Building a Tool Builder: Making AI Tools Configurable Without Code](https://danieljohnmorris.com/writing/building-a-tool-builder/): The first API had hardcoded tools. The Slack bot needed different tools. I built a tool system where admins create, configure, and monitor tools from a dashboard. - [Getting the Most Out of Cursor IDE](https://danieljohnmorris.com/writing/getting-the-most-out-of-cursor-ide/): After a year of daily use, here's what helps with AI-assisted development in complex projects. Context management, documentation, and knowing when to commit. - [From Flat Vectors to Graph RAG: When Similarity Search Isn't Enough](https://danieljohnmorris.com/writing/flat-vectors-to-graph-rag/): Vector search finds similar chunks. Graph RAG finds related concepts. The difference matters when questions span multiple topics. - [Chunk-Then-Summarise: The Embedding Pipeline That Worked](https://danieljohnmorris.com/writing/chunk-then-summarise/): Raw PDF chunks make terrible vectors. Summarising each chunk before embedding produced cleaner searches and more relevant retrieval. - [Pinecone to pgvector: Why I Ditched the Managed Vector DB](https://danieljohnmorris.com/writing/pinecone-to-pgvector/): Pinecone worked, but it was another service to manage, another bill, and another point of failure. pgvector kept vectors next to my relational data in the same Postgres instance. ## Projects - [ilo: A Programming Language for AI Agents, Not Humans](https://danieljohnmorris.com/projects/ilo-lang/): A performant language designed for LLMs to write. Optimised for token and character length, and rethought for non-human use cases. - [Self-Hosting on One Hetzner VPS](https://danieljohnmorris.com/projects/self-hosting/): One Hetzner CAX serving 33 hostnames behind Dokploy: analytics, error tracking, DMARC reporting, live chat, scheduling and a row of small apps, with measured memory for each. - [AI Coworkers: Not Just Chatbots or Agents](https://danieljohnmorris.com/projects/ai-coworkers/): Two codebases asking where a long-running AI coworker should live. ai-coworkers is a standalone TypeScript runtime driven by markdown job descriptions. hermes-governance is the same boundary model rebuilt as a Hermes plugin, to find out how much of it an existing host can carry. - [LLM vs JEPA](https://danieljohnmorris.com/projects/tiny-bouncing-jepa/): A five-part exploration of Yann LeCun's argument against generative video prediction. From-scratch JEPA on a synthetic bouncing ball, action-conditioned planning, and a DINOv2/v3 hover demo on a real image, all running on an M3 MacBook in under five minutes per part. - [5x5 Go](https://danieljohnmorris.com/projects/5x5-go/): Two playable 5x5 Go demos: a self-contained 2-ply minimax bot in one HTML file, and the same UI fronted by KataGo running on a small VPS. - [Token Efficiency: Where the Tokens Go](https://danieljohnmorris.com/projects/token-efficiency/): A running map of where an agent's tokens go: weights, retrieval, resident prompt, generation, and the loop. Revised when I measure a layer or a vendor revises a claim. - [AI Goban/Baduk Board Detector](https://danieljohnmorris.com/projects/baduk-board-detector/): Computer vision system that reads a physical Go board from a photo and outputs a digital board state. - [Three.js Experiments](https://danieljohnmorris.com/projects/threejs-experiments/): Browser-based 3D scenes, shaders, and parallax effects built with Three.js. The fluid backgrounds on this site come from this work. - [Agent Skills and MCP Servers by Area](https://danieljohnmorris.com/projects/agent-skills-and-mcp/): A running map of the skills, subagents and MCP servers I run, split by the work they do: product management, design, code review, business operations and codebase search. - [Conversational AI: From RAG Prototypes to Domain-Specific Supervision](https://danieljohnmorris.com/projects/counselling-supervisor-ai/): A series of conversational AI systems exploring streaming interfaces, contextual memory, tool-calling, and the progression from vector search through to graph RAG. Culminated in a counselling supervision tool grounded in 70+ professional documents from BACP, NCPS, and UKCP. - [DIY Swarmatron](https://danieljohnmorris.com/projects/diy-swarmatron/): Custom-built analog synthesizer inspired by the classic Swarmatron swarm synthesizer design. - [Site Blocker](https://danieljohnmorris.com/projects/site-blocker/): A Chrome extension that blocks sites for a duration you pick, where nothing in the popup can lift a block early.