Blog Archive
- Miko-bench: 65 AI Models Guess My Puppy's Breed Mix
I asked 65 vision models to rank Miko's likely breeds from the same evidence given to humans, then compared their guesses with her DNA results.
- My 2026 San Juan Softie 100 Race Plan
My 26-hour and 28-hour pacing plans, aid station splits, fueling, drop bags, lights, and weather strategy for the 2026 San Juan Softie 100.
- Triaging Gmail with Claude Subagents
A writeup of a small agentic system I built to triage my Gmail inbox, using Claude subagents to organize and assess messages.
- PostgreSQL from Google Apps Script
Connect Apps Script to PostgreSQL via JDBC, including connection strings, JSONB and UUID workarounds, transactions, and PostGIS.
- Fiction AST and GLiNER NER in Rust
How I built a fiction-specific AST and named-entity pipeline with LLM labeling, GLiNER fine-tuning, and ONNX inference in Rust.
- VS Code Git Remote Color
An open-source VS Code extension that hashes each workspace Git remote and colors the status bar to distinguish open repositories.
- Extracting Gold from Antigravity's Brain
A workflow for extracting architectural patterns and implementation challenges from AI agent walkthroughs to inform later engineering work.
- Agent Identity for Git Commits
How to configure AI agents to push commits to GitHub using a separate bot identity without modifying local git configuration.
- Building a MCP Client in Google Apps Script
Learn how to communicate with Model Context Protocol (MCP) servers using Apps Script and UrlFetchApp. Incorporate the MCP client into Vertex AI tool calling.
- Using Gemini in Apps Script
Use Apps Script's Vertex AI advanced service to call Gemini for text, images, structured output, search grounding, and multi-turn chat.
- Currentonly Scopes in Google Apps Script
How Apps Script currentonly scopes limit access to an active file, and why Advanced Services, direct API calls, and openById need full scopes.
- 2026 Crazy Mountain 100
I'm running the Crazy Mountain 100 in 2026! It's a rugged 100 miler in Montana that serves as a Hardrock qualifier.
- Resolve Chat User IDs to Emails: Least Privilege
Securely resolve Google Chat User IDs to emails without Domain-Wide Delegation. Use Service Account Impersonation and custom Admin roles.
- Apps Script CacheService Limits
Unofficial Apps Script CacheService findings: key and value limits, FIFO batch eviction, edge cases, and practical cache patterns.
- UrlFetchApp: The Unofficial Documentation
The unofficial guide to Google Apps Script UrlFetchApp. Master authentication, fetchAll for parallelism, web scraping, and debugging "Address Unavailable".
- Secure Secrets in Google Apps Script
Avoid hardcoded Apps Script secrets by using PropertiesService for configuration and Google Cloud Secret Manager for sensitive values.
- Protect Gmail AI Agents with Model Armor
Use Model Armor in an MCP tool handler to block prompt injection and redact sensitive Gmail content before it reaches an AI agent.
- React Wrapper for Google Drive Picker
Announcing the new React component for the Google Drive Picker, wrapping usage of the web component for easier integration.
- Google Workspace Developer Tools MCP Server
Announcing the new MCP server for Google Workspace Developer Tools, providing AI agents with access to official documentation and API snippets.
- Google Workspace Developer Tools VS Code Extension
Announcing the new Google Workspace Developer Tools extension for VS Code, working with Antigravity and providing OAuth2 scope linting and MCP support.
- Google Drive Picker TypeScript - Types Updated
A DefinitelyTyped update that replaced community Google Drive Picker types with autogenerated types from the official reference source.
- Google Forms - title vs name vs documentTitle
Recently I had to clarify some confusion around the title and name of a Google Form. Here is a quick explanation of the difference between the two.
- Convert docx to Google Docs with Apps Script
Programmatically convert, open, and edit Microsoft Word .docx files in Google Apps Script using the Drive API and DocumentApp.
- Allow Sheets IMPORT and IMAGE URLs
Use the Sheets API to allow external URL access for IMPORT and IMAGE functions without requiring each spreadsheet user to grant consent.
- Google Workspace Developer Summits 2024
Save the date for the 2024 Google Workspace Developer Summits in Boston on September 12 and Berlin on September 17.
- Chrome sidePanel API Access
Link shared about: How do I get access to the chrome.sidePanel API from the latest manifest v3? - Stack Overflow
- Colorado River Basin Alfalfa Water Use
A shared report that alfalfa grown for beef and dairy uses more Colorado River Basin water than all cities and industries combined.
- Apps Script and WebAssembly - A comprehensive guide
You can use WebAssembly with Google Apps Script! This post will cover how to do that and provide a comprehensive guide on how to get started.
- SvelteKit UUID Slugs in a Derived Store
A SvelteKit store pattern that converts URL-safe base64 UUID slugs back to UUIDs in route parameters, with implementation examples.
- google.script.run vs. doGet/doPost
Compare google.script.run vs doGet/doPost endpoints for Apps Script web apps. Choose the best method for simple apps or complex frameworks like React/Vue.
- TDS at UTMB Mont-Blanc
I signed up for the UTMB TDS race in the Alps, with friends for UTMB week and four running stones on the line.
- Feds May Be Underestimating Broadband Woes
A shared Colorado Sun report on the FCC broadband map, plus my concern that local providers overstate availability and ignore latency.
- Drive File Get Blob and Scopes in Google Apps Script
Compare DriveApp, the Drive Advanced Service, and UrlFetchApp for retrieving Drive file blobs in Apps Script while minimizing OAuth scopes.
- Apps Script Storage Benchmarks
Benchmarks comparing CacheService, PropertiesService, and Firestore in Apps Script, including speed measurements and when each storage option fits.
- Google Cloud Region Latency in Google Apps Script
Ping results to Google Cloud regions and short code snippet demonstrating how to measure latency from Google Apps Script.
- Optimizing Parallel Jobs in a Github Workflow
A GitHub Actions pattern that saves a built workspace so preview, test, and matrix jobs can run in parallel without rebuilding.
- Apps Script V8 Runtime Limitations
A comparison of the WinterCG minimum common web APIs and Apps Script's V8 runtime, including UrlFetchApp and sleep workarounds.
- Rust, Python, and WASM in Apps Script
A Google Next 2024 lightning talk on extending Apps Script with Rust, Python, and WebAssembly, with a build demonstration.
- Promises, async and await in Google Apps Script
Understand async/await and Promises in Google Apps Script. Learn why most APIs remain synchronous and how WebAssembly is the exception.
- Cloudflare Workers: Dev, Staging, and Prod
Configure Wrangler environments for Cloudflare Workers, then use GitHub Actions to deploy and promote changes through dev, staging, and production.
- Google Calendar - Usage Limits Exceeded
Understand why Google Calendar reports "usage limits exceeded" for external attendees and notifications, plus practical alternatives.
- Embed images from Google Drive in your website
Google Drive broke the ability to embed images with the /uc path. Here's how to embed images from Google Drive in your website.
- Apps Script Service Account Impersonation
Avoid downloading service-account keys: use impersonation in Apps Script to mint access tokens for Google Cloud APIs.
- Using Firestore in Apps Script
Use the Firestore REST API from Google Apps Script when CacheService, PropertiesService, or Sheets cannot meet your storage requirements.
- Optimized Dockerfile for Rust
A multi-stage Rust Dockerfile that caches dependencies with a dummy main.rs before copying source into a slim Debian runtime image.
- Generating Text with Gemini Pro in Apps Script
A short Apps Script example that calls the Gemini Pro REST API to generate text, then reads the response candidate text.
- Using Vertex AI in Apps Script
How to use the Vertex AI API in Apps Script to make predictions on your data or use it in any of your other Google Workspace processes.
- Memoization in Apps Script
A generic Apps Script memoization helper that hashes a function and arguments, stores results in CacheService, and explains its limits.
- Building a Google Chat App with n8n
How I used an n8n webhook workflow, Google Chat slash command, and Cloud Translation API to build a simple translation chat app.
- Combining Google Workspace Add-ons and Editor Add-ons
Both Add-on types have their own strengths and weaknesses. Combining them could be a powerful way to build Add-ons for Google Workspace but with some caveats.
- Moab 240 Training Camp
A three-day Moab 240 training camp covering 92.79 miles and 17,123 feet on high, technical sections of the course before race day.
- A Trail Marathon Race Win Was Stolen From Me
I crossed the Enchanted Forest Trail Marathon finish first after completing the full course, but runners who skipped 3.8 miles won.
- Rust Compiler Whack-a-Mole
Notes from a Rust terminal UI prototype for PlexAmp, covering Tokio tasks, channels, select!, and questions left to explore.
- Email Magic Links with Cloudflare Pages
Build passwordless email login with Cloudflare Pages, Functions, KV, and SendGrid: create and validate tokens, then set a session cookie.
- Recovering from a 100 mile ultramarathon
A week after the Canyons 100, my HRV, resting heart rate, and respiratory rate still show the cost of a 100-mile effort.
- Google User Credentials in non-interactive workflows
Use an OAuth2 offline flow to obtain Google user credentials as application default credentials when service accounts or API keys cannot work.
- Verify a Google access token
A simple endpoint for checking whether a Google OAuth access token is valid, useful when troubleshooting authentication and API requests.
- Automator's Hole
A reflection on the gap between manual work and automation, where a task remains too small to automate but too tedious to keep doing.
- A look back at running in 2022 and plans for 2023
A look back at nearly 2,400 running miles in 2022, the races that defined the year, and my ultramarathon plans for 2023.
- La Sportiva Cyklon Cross GTX Review
My early review of the La Sportiva Cyklon Cross GTX: warm, grippy winter runners with a Boa closure, gaiter, and a narrow toe box.
- Track all Firestore write activity in Firestore
Capture Firestore writes as per-user activity by routing Audit Logs through a Pub/Sub sink to a Cloud Function that writes Firestore.
- 2022 Mogollon Monster 100 Mile Race Report
A 2022 Mogollon Monster 100 race report: I led early, battled ankle and calf injuries, exhaustion, and nausea, then finished 15th.
- 2022 Moab 240 DNF
Notes from my 2022 Moab 240 DNF at Shay Mountain, where an already-injured Achilles worsened despite a strong first 70 miles.
- Strongly Typed Yup Schema in TypeScript
A TypeScript pattern that uses generics and conditional types to make Yup schemas strongly typed, with examples that satisfy the compiler.
- Docker Buildx, GCR, and GitHub Actions Guide
Authenticate and push to Google Container Registry (gcr.io) from GitHub Actions using the docker/build-push-action and Google Cloud Auth.
- Docker Build Secrets in GitHub Actions
Pass a GitHub secret as a docker/build-push-action build argument, then expose it in each needed Dockerfile stage.
- Caching Playwright Binaries in GitHub Actions
A GitHub Actions caching strategy for Playwright browser binaries that reduces repeated downloads and speeds up browser-based CI runs.
- Mogollon Monster 100 Mile Planning
My 2022 Mogollon Monster 100 planning notes and target splits, built around a 24-hour goal after an 11th-place finish the year before.
- 2022 Creede 100 Race Report
A 2022 Creede 100 race report: I led for 80 miles before altitude and cold affected my breathing, then finished second in 29:16:01.
- 2022 Mace's Hideout 100 Race Report
A race report from the 2022 Mace's Hideout 100-mile ultramarathon, where I finished third in 29:20:53 after a long night on the course.
- Unwatch All Repositories in a GitHub Organization
Use the GitHub CLI to list watched repositories in an organization, filter them, and delete each subscription without manual clicks.
- Strava Webhooks with Stokehook.com
A Svelte and Firebase app that receives Strava webhook events through Stokehook, built to explore the Strava API.
- Archiving Dependabot Emails with Apps Script
Archive Dependabot and Semantic Release emails automatically using Google Apps Script cron jobs to declutter your inbox.
- Rebasing All Dependabot Pull Requests
A shell command using the GitHub CLI search and comment features to ask Dependabot to rebase pull requests across an organization.
- Auto-Merge Dependabot Pull Requests
A GitHub Actions workflow that approves and auto-merges Dependabot pull requests while relying on branch protection and required checks.
- What is DevRel?
DevRel is a lot things: marketing, engineering, product management, support; my experience as a Developer Relations Engineer at Google.
- Drop Bag Plan for Cocodona 250
Running a 250 mile race without crew or pacers requires adaptability and a good plan for drop bags. This is a work in progress...
- Eleventy Related Posts Using TF-IDF
Automating related posts in Eleventy with term frequency-inverse document frequency and eleventy-plugin-related.
- Running and Chronic Exertional Compartment Syndrome
Understanding and treating a new running injury, Chronic Exertional Compartment Syndrome. Can I run? Can I race?
- GitHub Workflow to Sync Branches
A GitHub Actions workflow pattern for synchronizing branches across a repository without relying on a third-party GitHub Action.
- 2022 Sedona Stage Race Report
Race Report for the 2022 Red Rocks Stage Race in Sedona, AZ. I finished the 50k Saturday, 50k Sunday version second overall in a little over 11 hours total.
- Eleventy Progressive Web App
A short look at turning an Eleventy site into a progressive web app while chasing better Lighthouse scores and improving offline behavior.
- What about the cows...
A critique of public-land grazing in the West, where protections for fragile cryptobiotic soil crust coexist with livestock damage.
- 2022 Behind the Rocks 50k Race Report
A race report from the 2022 Behind the Rocks 50k in Moab: 8th in 4:55 after a hot, sandy course and a rough race week.
- Mountain Bike Bear Spray Holder
Instructions for making a DIY mountain-bike bear-spray holder that keeps the can accessible while riding on trails in bear country.
- 2021 Mogollon Monster 100 Mile Race Report
A race report from the brutal 2021 Mogollon Monster 100, where heat, dehydration, and nausea still led to an 11th-place finish.
- Google Maps React Wrapper
A React wrapper for loading the Google Maps JavaScript API, keeping map setup and script loading in a reusable component.
- Molas Lake to Vallecito Reservoir
A solo 36-mile run from Molas Lake to Vallecito Reservoir through the Weminuche Wilderness, following the Colorado and Continental Divide trails.
- Automate Email Bankruptcy using Apps Script
An Apps Script that archives Gmail threads older than 30 days, respects Gmail's 100-thread batch limit, and runs hourly on a trigger.
- WMS Layer on Google Maps
How to add a Web Map Service layer to Google Maps by converting tiles to Web Mercator bounds and building GetMap request URLs.
- Microservice Logging with Openresty and BigQuery
Log microservice usage and bytes sent directly to Google BigQuery using OpenResty and Lua for accurate billing and analytics.