I build small tools for AI coding agents: Claude Code, Codex, MCP servers and agent skills.
By day I look after systems and infrastructure, and manage open source projects, for a not-for-profit in Australia. Everything here is personal work.
- ai-quota-meter: shows your remaining Claude Code quota on the status line, using Anthropic's own numbers, and switches on Codex's built-in quota display. A single static binary with no network access.
New tools are released under Sigilet Labs.
Fixes merged into other people's projects. One dot per merged pull request.
Every merged pull request, one line each
- neuledge/context#125: only skip repo-meta filenames at the scan root
- neuledge/context#126: Go module support for the docs registry
- neuledge/context#166: skip test and example directories only at the repo root
- neuledge/context#173: generic types and JSX inside code examples stay in the docs index
- neuledge/context#175: section titles keep words inside bold, italics, links and code, so Python doc sections stop being indexed as "Introduction"
- neuledge/context#190: prose sections with long link URLs are indexed instead of skipped as tables of contents
- neuledge/context#206: pages without a frontmatter title are named by their
# h1instead of their file name, so Python doc pages stop showing up aslogging-cookbook.html - neuledge/context#208: long Markdown sections are split outside code blocks, so a code example with blank lines in it stays in one piece
- yetone/magpie#88: the gateway reports a Claude reply cut off by the context window as cut off
- yetone/magpie#128: gateway ids made in the same clock tick stay unique
- Yeachan-Heo/oh-my-claudecode#4152: the git guardrail hook also catches
git --no-pager pushand other global options - Yeachan-Heo/oh-my-claudecode#4160: the code-simplifier hook reads the global config from
~/.configon Linux, where the docs put it - Yeachan-Heo/oh-my-claudecode#4161: Copilot and Cursor rule globs like
**/*.pyalso match files at the top level - Yeachan-Heo/oh-my-claudecode#4177: the directory-context hook stops adding a sibling folder's README and AGENTS.md
- microsoft/conductor#572: a
$before a{{ }}expression no longer stops a workflow loading - volcengine/OpenViking#5448:
ovcli.confaccepts theoidc_tokenand trusted-mode settings the Rust CLI already reads - NVIDIA/SkillEvaluator#168: the PII scan stops reporting Chrome User-Agent versions as IP addresses
- freescout-help-desk/freescout#5683: toolbar icons, stars and menu toggles can be reached with Tab and pressed with Enter or Space
- microsoft/SkillOpt#295: the sleep harvester stops reading skill text Claude Code injects as things the user typed
- dmno-dev/varlock#1169: the standalone binary can start its encryption helper when run from a directory the user cannot enter, so
varlock cache clearworks for service users - freescout-help-desk/freescout#5692: confirmation dialogs focus the primary button, so Enter confirms
- freescout-help-desk/freescout#5693: deleting a conversation opens the next active one when that is the after-send setting, as a status change already does
- vectorize-io/hindsight#4870: the MCP
recalldocs say whatmax_tokenscounts - axllent/mailpit#742:
_and%in a search match themselves instead of acting as wildcards - axllent/mailpit#743: address searches like
from:"Marks & Spencer"find names containing&or\ - axllent/mailpit#757: negated
larger:,smaller:,after:andbefore:searches return exactly what the plain search leaves out, so a message on the boundary is no longer in both results or in neither - morluto/rea#1985: .NET assemblies precompiled for Linux or macOS open in the managed inspection tools instead of failing as an unsupported architecture
- morluto/rea#2730:
rea uninstallremoves only its own row from a shared DeepSeek Harness patch, and keeps the user's settings and comment - morluto/rea#2117: WebAssembly modules too large to disassemble get a short size-limit error instead of 33 MB of output and advice to run
rea doctor - morluto/rea#2096:
rea setupfor Hermes accepts aconfig.yamlthat holds only comments or a---marker, and keeps them - morluto/rea#2116: comparing two .NET assemblies pairs each member with its own type and name first, instead of matching it to an identical member of another type
- morluto/rea#3059: comparing two builds of a .NET assembly pairs members whose signatures name the same types at different metadata rows, instead of reporting them removed and added
- curl/curl#23469:
-O -Jfalls back to the name from the URL when the server sends an emptyfilename="",.or.., instead of failing with error 23 - ublue-os/ucore#458: uCore on aarch64 no longer runs out of space in
/bootwhen rebasing from Fedora CoreOS, because it drops the devicetree files CoreOS drops - holepunchto/dht-rpc#133: closing a session releases each of its requests from the congestion window once, not twice
- jgm/pandoc#12007: converting a Jupyter notebook with long cell output no longer slows down with the square of its length (a #7744 notebook: 41 s to 1.4 s)
- stripe/link-cli#370:
--authwithout a path is refused instead of logging out the default session - ahmad-a0/silverbullet-mcp#19: the note-editing tools only write
.mdnotes - zvec-ai/zvec-grep#229: managed
rgsearches keep their globs and ignore rules when the search path starts with. - Mbed-TLS/mbedtls#11002: the
cert_writeandcert_reqsample programs accept IPv6 addresses insan=IP:without overflowing the stack, and keep each IP entry's own address (backports #11003, #11004) - aicodeking/leanrea#2: the skill's piped commands run as written, instead of passing
|to the first command as an argument - holepunchto/hyperdht#317: after a relayed connection upgrades to direct, the server remembers the direct path to the client for reuse instead of the relay's address
- Exiv2/exiv2#9553: image files shorter than 80 bytes, such as a tiny GIF or BMP, are recognised instead of reported as an unknown image type
- jgm/ipynb#4: notebooks whose outputs have a null execution count, which the format allows, can be read instead of being rejected
- axllent/mailpit#759: the link check finds a link at the very start of a plain-text message, such as a password-reset email that is just the link
Issues filed: SkillSpector#638, #639, #640, SkillEvaluator#167, silverbullet-mcp#20, chrome-agent#12, scc#783, hindsight#5371, gitea#39651, rea#4797, #4806, #7226, pandoc#12008.

