Latest release
v0.2.24
- feat
Exact string edits no longer need op=str_replace: if you pass old_string and new_string without op, the edit runs as a unique exact replace instead of failing with no content provided.
Current release
v0.2.24
1 changes in this release. Read the full archive below.
Latest release
Exact string edits no longer need op=str_replace: if you pass old_string and new_string without op, the edit runs as a unique exact replace instead of failing with no content provided.
Release
Memo caches are private to your local OS user and reject unsafe file links.
Clearing migrated memo caches keeps them cleared.
Release
Read and edit failures now say what actually happened instead of a bare "cannot read file": file not found, permission denied, path too long, or is a directory — and for relative paths the error includes the resolved absolute path plus a note that relative paths resolve against the daemon's launch cwd, so a wrong-worktree call is diagnosable at a glance (codegraff#475).
Fixed a daemon-crashing bug: reading a directory path panicked the entire codedb-pro MCP server — the zero-copy mmap path is unreachable on directory fds and std treats that as a crash. Non-regular files now skip mmap and return a clean "is a directory" error.
Release
Repeated edits to the same file no longer re-map it from disk. The edit path now snapshots from the stat-validated content cache instead of a fresh mmap — on macOS, mapping a file an atomic rename just replaced cost ~7.6ms per 3.2MB versus ~0.26ms for a plain read. Edits to a 3MB file measured 13.7ms before and 8.5ms after.
Edit-path cache loads skip the read-only metadata passes (warnings, hash, revision) that edits never consume, while reads always reload them in full. 3MB edits measured 8.5ms before and ~4ms after — faster than a plain non-atomic rewrite of the same file, with the atomic write and on-disk verification unchanged.
The snapshot cache retains files up to 8 MiB (budget 32 MiB), so 4–8MB sources keep the fast path: a 4.7MB file measured 9.3ms per edit before and 7.9ms after. Daemon memory stays hard-capped — 72MB churned through the cache held RSS flat at 41MB.
Diff synthesis no longer scans the file from byte zero to locate the edit; it starts at the byte offset the line index already computed.
Release
zigpatch --all replacements now verify on disk before reporting success. A pre-rename fence refuses to overwrite a file that changed since it was read, and a post-write re-read confirms the spliced bytes survived, so a concurrent editor produces a loud retryable error instead of a silently lost edit.
In an eight-way concurrent replace measured over twenty rounds, 0.2.19 reported success for four edits that never reached the file; this build reported zero.
Successful replacements carry a verified:true field, and a replacement identical to its pattern is rejected as a no-op instead of claiming success.
Release
Warm reads now retain files up to 4 MiB in a pinned snapshot cache bounded to 16 MiB total. Against v0.2.18, cached 100 KiB, 500 KiB, and 2 MiB line reads measured 3.62×, 17.38×, and 90.76× faster at median latency; unchanged reads measured 4.52×, 20.34×, and 109.26× faster.
Reads return strong revisions and support if_revision. Semantic edits can reject stale snapshots, exact string replacement preserves files without a final newline, and expert byte deltas require a matching base revision. All targeting and writes use one immutable snapshot and refuse intervening external changes.
Default anchored writes measured 1.21× faster at both 100 KiB and 1 MiB. Guarded byte deltas were another 1.09× to 1.11× faster than guarded anchored edits, while a ten-file 2 MiB working set stayed within the 16 MiB cache budget.
Tool discovery now presents 11 focused choices instead of two identical exact-search schemas. Existing search calls remain compatible, while clearer descriptions distinguish exact from exploratory search, targeted edits from known-line patches, whole-file creation, cross-file replacement, and safe batching.
The modern tools/list response is 15,406 bytes versus 16,333 in v0.2.18—5.7% smaller, or roughly 232 fewer prompt tokens—even with the new revision and byte-delta fields.
Release
Modern MCP clients can opt into native structuredContent instead of receiving JSON serialized inside a text block. Representative medium reads are 22% faster at median latency with 8% fewer response bytes, while existing clients keep the previous response shape by default.
Batches now use bounded eight-operation waves and the caller thread for one operation. Two-, four-, and eight-read batches measured 30%, 20%, and 10% faster at median latency, while meta_search identifier fan-out improved by 8%.
Wide batches cap retained result data at 64 MiB and return an explicit batch_output_limit error. Multi-path replacements now serialize conservatively so overlapping path sets cannot race other reads or writes.
Recent reads and edits now influence search ranking consistently whether an agent invokes them directly or through a batch.
Release
Modern MCP hot calls are 9% faster at median latency and 5% faster at p95 than v0.2.16, measured across eight alternating 100,000-call ReleaseFast rounds.
On an already-running daemon, a stateless MCP 2026 first call is 52% faster than the legacy initialize-plus-call path: 7.5 versus 15.75 microseconds at median latency.
Responses now reserve their final capacity and newline-delimited replies use one write. Modern tool discovery also avoids a duplicate catalog copy while preserving the same schema, response bytes, Content-Length framing, and local-only data boundary.
Release
MCP 2026-07-28 clients can now use server/discover, tools/list, and tools/call as self-contained stateless requests. Every modern response carries resultType and server metadata, tool discovery includes private cache hints, and unsupported protocol revisions return version data for a clean retry.
Existing clients keep the initialize-based MCP flow through 2025-11-25. Both protocol eras use the same local stdio subprocess: repository paths, search queries, file contents, edits, and tool results are not sent to a remote MCP host.
MCP reads are leaner and can omit line-number gutters with numbers:false. Search supports bounded A/B context lines, while anchored replacement adds replace_all, expected match counts, symbol scoping, and explicit ambiguity details.
Reliability fixes prevent zigrep from dropping matches when regex scratch space saturates, make zigmemo writes fail closed, preserve valid zigdiff JSON for very long values, and report zigpar truncation when capped output feeds a dependent operation.
Release
Direct pipe searches no longer wait for a 50 ms watchdog polling interval. Across 150 alternating ReleaseFast samples of the same directory query, median latency fell from 54.3 ms to 0.68 ms (79.5x) and p95 from 56.9 ms to 1.38 ms (41x), with byte-identical output.
MCP batches now normalize arguments once, keep their response in memory, and avoid thread startup for bounded traversal reads while preserving parallel execution for heavier work. A four-file mapping batch improved from 787 to 464 microseconds (1.70x), and an eight-operation traversal improved from 2.31 to 1.48 ms (1.56x).
Agent tool context is leaner: tools/list shrank from 25,946 to 15,904 bytes (38.7%, roughly 2,510 fewer input tokens) without removing tools, fields, defaults, or safety controls. replace also correctly advertises its path-or-paths input alternatives.
Fresh installs can use every core CLI's --help and --version before activation, while operations that inspect or edit working data remain protected by the offline license. Source users can run scripts/source-check.sh check to reproduce the CI build, test, and smoke contract locally.
Release
The full 13-tool release now builds with the exact Zig 0.17 development snapshot pinned in the repository, including working image compression in both Debug and ReleaseFast builds.
macOS releases now reserve signing-header space and verify that codesign preserves executable text. Intel binaries are executed under Rosetta before upload instead of trusting signature validity alone.
In nine alternating A/B rounds on a deterministic 600-file search benchmark, the migrated build was 3.6% faster at median latency for full-directory searches and 8.7% faster across all 13 scenarios than the Zig 0.16.0 build. These are build-to-build measurements rather than compiler-only attribution.
Release
Edit and patch now fail closed around stale or ambiguous targeting. Symbol edits resolve against current file contents; unknown operations, conflicting positioners, malformed or reversed ranges, line zero, and match_index without a pattern are rejected before writing. The MCP schema now documents match_index, whole_file, and scope-shrink confirmation.
Search-index filtering is recall-safe. Eligible files are indexed in full, while incomplete walks, capacity limits, oversized files, regex searches, and no_ignore:true fall back to the complete walker. Full reads are not capped at 500 lines, and limit:0 is explicitly unlimited.
MCP edit and patch responses now write directly to the response buffer instead of creating an OS pipe and drainer thread for every call. In a persistent ReleaseFast dry-run benchmark this raised throughput from 3,990 to 27,879 operations per second (6.99x), cut median latency from 225.1 to 34.7 microseconds, and preserved byte-identical normal responses.
Response-capture allocation failures discard partial output. If a mutation may already have committed, the failure carries outcome_unknown:true so callers do not blindly retry the edit.
Release
Search just works with regex patterns. A pattern that contains regex syntax (alternation like a|b, character classes, or .* / .+ quantifiers) is now auto-interpreted as a regex even without setting regex:true, so searching for upstreamConfig|resolveModel finds both terms instead of silently returning zero matches. The response notes interpreted:"regex" when this happens, plain-literal searches behave exactly as before, and a pattern that is not valid regex falls back to a literal search instead of erroring.
Clearer zero-match guidance. When a literal search finds nothing, the hint now points at the likely cause (for example, the pattern looks like a regex, so pass regex:true) instead of always suggesting a broader path.
Release
Faster install and update: the curl install.sh | sh command now downloads every binary at once instead of one after another. The eight toolchain tools plus codedb are fetched concurrently, so the download phase takes about as long as the single slowest file rather than the sum of all of them (roughly 7x faster in a local benchmark). Per-tool status still prints in order, and because codedb-pro update re-runs the same installer, updating gets the identical speedup.
Fixed: a fresh install could stop before wiring up your editor. On a machine with no previous version to migrate, the installer step that removes older versions returned a non-zero status that, under strict error handling, silently aborted the rest of the run, so Claude Code, Codex, Gemini, and Cursor were never registered and codedb was never installed. New installs now finish every step, and codedb-pro update no longer reports a false failure.
Release
zigrep -g/--glob: ripgrep-style file filters, repeatable up to 16. '!'-prefix excludes, '!dir' prunes whole directory subtrees during the walk, and globs containing '/' match the path relative to the search root. Works in content search, --files, -F find mode, and -R replace (excluded files are never modified). Glob searches run on the parallel engine path: 5.4 ms vs ripgrep's 12.5 ms on the same query, 2.3x faster.
zigpatch --all: replace or delete EVERY occurrence of a pattern in one atomic write, like sed s///g but byte-exact (a file without a trailing newline keeps that shape, and a replacement containing the pattern can't recurse). Composes with --dry-run, --backup, and --undo. 1,667 replacements across a 5,000-line file land in 2.2 ms, ahead of sed at 2.8 ms. Pattern mode (-p, --scope, --match-index) is now documented in --help.
zigpar: edit ops accept pattern / all / matchIndex / scope and search ops accept glob / globs, so the new zigrep and zigpatch features work inside batched manifests. Scheduling is now dependency-chained: an op waits only on the ops it actually conflicts with instead of on whole-batch barriers, so a search plus an 8-edit chain runs 1.7x faster (36 ms to 21 ms).
Fixed a macOS Apple Silicon bug where an op's completion was gated by the slowest sibling op started at the same time: pipe file descriptors leaked into concurrently spawned children because fcntl was declared with a fixed-arg signature (variadic args land on the stack on ARM64), so FD_CLOEXEC never actually stuck. The fix applies to the whole toolchain, including muonry's own diff drainer.
Release
Edit responses are now metadata-sized. The diff is synthesized directly from the edit instead of forking `git diff` per edit: edits are ~1.3x faster, the diff shows only this edit's delta (not the whole working tree's), and you get diffs outside git repos and on dry_run previews too. A whole-file replace no longer echoes the entire file back twice: 169 KB → 1.9 KB on a 2,000-line file.
Search output is capped and grouped. New limit (default 500 lines) and max_per_file (default 25) parameters keep a low-selectivity pattern from dumping megabytes into your context. Responses carry limited:true plus a refine hint when the cap fires, and capped files end with a '+N more matches' marker. Matches are now grouped per file under a relative-path header instead of repeating the absolute path on every line: 11.8x less output on broad searches.
Reads now flag hidden content. Unicode tag blocks, variation selectors, and confusable (look-alike) characters are decoded and surfaced in a warnings field, so text smuggled into a file to steer an agent is made visible instead of silently ingested. Warnings now appear on batch and MCP daemon reads too, not just the CLI.
Opt-in secret scan: set MUONRY_CRYPTO_SCAN=1 and reads warn on private keys, seed phrases, API secrets, and wallet address-poisoning lookalikes before they reach the model. Off by default so the fast path stays fast.
Search skips vendored zig-pkg directories, matching the other dependency-dir rules.
Measured against v0.2.6 with byte-identical operations through the daemon pipe: whole-file replace responses are 20.5x smaller (165 KB to 8 KB on a long-lined 2,000-line file) and 15x faster, single-line edits are 30x faster (9.6 ms to 0.32 ms, the cost of the removed git diff fork), and a broad search returns 14.7x less output (286 KB to 19.5 KB).
Release
Frecency ranking now actually works. Search results are ranked by the files you've read and edited — the recording step was wired up but never called, so every score was 0 and the ranking did nothing. Recency is weighted for agent workloads (3-day half-life); set MUONRY_FRECENCY_MODE=normal for the classic 10-day curve.
Recently-modified files rank higher, so a file you just edited surfaces in results even before you've searched for it.
Search now respects .gitignore. Build output, node_modules, and other ignored paths no longer clutter results — pass no_ignore:true to include them.
Typo-tolerant filename find: pass fuzzy:true and a find that returns zero exact matches now suggests the closest filenames instead of nothing.
Safety: replace refuses a runaway apply touching more than 50 files unless allow_large:true, guarding against a transposed search/replace rewriting the whole tree. And edit by symbol or pattern is no longer hijacked by a stray after:0.
the daemon could segfault on repeated reads of an untracked file (a use-after-free in the frecency tracker). Fixed.
MCP initialize now negotiates protocolVersion — it echoes the client's requested version when supported instead of hardcoding the latest, so spec-strict clients pinned to an older revision stay connected.
Release
zigread: SIGBUS guard on mmap reads. If a file is truncated between stat and access, zigread now falls back to a buffer read instead of crashing. Same protection muonry has had since v0.2.0.
zigread: RSS monitor with 512 MiB cap. If the process exceeds 512 MiB resident memory, zigread aborts with a clear error instead of getting OOM-killed by the OS.
zigread: image files (PNG, JPEG, GIF, WebP, BMP, ICO, SVG) in pipe mode now return base64-encoded data with MIME type, matching muonry's format. Non-image binaries still get the text summary. 10 MiB raw size cap with OOM guard on the base64 allocation.
zigpatch: scope shrink guard threshold lowered from 20:1 to 10:1. Pattern-mode edits that resolve to a scope >10x larger than the replacement are now refused with an actionable error message. Verified across C, C++, Go, Python, Java, TypeScript/TSX, and Rust.
Release
muonry --changelog: new flag prints the embedded release-notes timeline inline, mirroring this page. Works offline and is the same content the MCP server now mentions in its initialize response, so agents can also surface 'what changed' to users.
muonry --version now hints at the changelog and update commands, so first-time users see how to upgrade and what's new without having to leave the terminal.
MCP initialize advertises the running version + changelog hint in its instructions field. An agent connecting to muonry can tell the user `running v0.2.4. Run muonry --changelog to see what's new, or muonry update to install the latest`.
Defensive fix: runVariantCapture (a currently-dead-code path inside handler_search) now sets up its own threadlocal SearchCtx, mirroring handle()/handleBuf(). Prevents a silent truncation-flag drop if the path is ever revived.
Release
muonry: parallel meta_search no longer hangs. Two concurrent search variants (or two ops in a parallel batch) used to share a module-level cancel flag inside handler_search; one variant's cleanup could clobber another variant's timeout signal, leaving the second variant's search loop spinning until it hit the 30-second daemon-wide budget. cancel_flag and truncated_any are now per-call state, so concurrent searches no longer step on each other.
muonry: lazy frecency-tracker init no longer holds the global mutex across disk I/O. The first search on a cold daemon used to open the frecency log under the lock; if disk was slow or the path was on NFS, every concurrent search blocked behind that read. Now the load happens outside the lock with a double-checked re-acquire on completion.
muonry: file cache no longer double-loads the same path under concurrent misses. Two simultaneous reads of an uncached file used to do two disk reads and two allocations, then evict each other's entry. The re-acquire path now detects a peer's load and frees the duplicate.
muonry: per-request arena now covers the full dispatch path (handler scratch, batch worker scratch, response writers), not just the line + JSON parse. Future leaks inside any handler become single-request bumps that get reclaimed at iteration end, instead of permanent growth.
Release
muonry: each pipe-mode request now runs against a per-iteration ArenaAllocator that owns the line buffer and parsed JSON tree. Reset between requests with a 1 MiB retention cap, so future entry-path leaks can't accumulate across long-running daemon sessions. Same behaviour for MCP mode.
Release
muonry: memo store/error/plan no longer goes silent past the 16 MiB read cap. Once the per-scope JSONL log grows past 4 MiB, the daemon now rewrites it in place keeping the newest entries that fit in 2 MiB. Atomic via tmp+rename. Tunable via ZIGMEMO_COMPACT_TRIGGER / ZIGMEMO_COMPACT_TARGET if the defaults don't fit your workflow.
muonry: frecency tracker now caps its in-memory file table at 5000 entries with LRU eviction (oldest most-recent access wins the boot). Long-running daemons that traverse millions of unique paths across multiple repos no longer accumulate per-path state without bound.
Release
zigrep -R and muonry replace are now feature-identical: multi-path (positional args / paths:[] array), regex with backreference fallback, dry-run, opt-in atomic_write. The same surface area on the CLI and in MCP.
Default replace is in-place truncate. 4.92× faster than `find -exec sed` and 2.37× faster than a python3 walk on a 500-file directory. The previous tmp+rename atomic write is opt-in via --atomic-write / atomic_write:true, and now preserves file mode, xattr, and ACL via fcopyfile(COPYFILE_METADATA) on macOS instead of silently dropping them.
Read-only files (0444) are now correctly refused with files_changed:0 in both tools. The old atomic-rename path silently bypassed file permissions through the directory's write bit; in-place fails with EACCES the way Unix expects.
Cross-platform fix: on Linux, createFile / open / sigsetjmp now resolve to the right libc symbols. Eleven tools were shipping with macOS-only open(2) flag values that aliased the wrong bits on Linux. zigrep, muonry, and every sibling tool build and test clean on linux-x86_64 again.
Release
zigrep: 1.59× faster than fd 10.4.2 for file enumeration on large trees. On a 78K-file Homebrew Cellar walk, --files now runs in 66 ms (was 106 ms; fd 84 ms) and `-F '*.h'` runs in 55 ms (was 72 ms; fd 87 ms). Each worker batches path output in 64 KB chunks instead of taking the stdout lock per file, dropping write() syscalls from ~78K to ~80 per run
zigrep: fixed silent output truncation on dense patterns over real source files. `[a-z]+` against a 3,805-line file previously emitted 1,203 of 2,951 matched lines with no warning. The 128 KB per-file output buffer overflowed and the safety break dropped the rest. Output now matches ripgrep byte-for-byte; the per-file output buffer is heap-sized at 16 MB
zigrep: search wall time on small files dropped from ~56 ms to ~3 ms. The cancellation watchdog was polling every 50 ms, so the worker join after a fast-completing search waited up to a full poll interval before returning
Release
Linux fix: createFile, createFileExclusive, and createFileAppend now actually behave as documented on Linux - the underlying syscall flags were Darwin-only numeric values, so on Linux edits silently appended garbage instead of truncating, exclusive-create did not enforce exclusivity, and append-mode writes raced and corrupted the frecency log under concurrent ops. x86_64 and aarch64 builds both fixed
memo store works after the first call in any session - was opening with O_RDONLY and then trying to write to the file, succeeding only on the very first store (which used the create-fallback path) and silently failing every subsequent one with 'memo: write failed'
Release
zigrep `-E` / `--regex` flag exposes the real PCRE-style regex engine that the matcher already had compiled in. Without `-E`, patterns remain literal substring matches; with `-E`, alternation (foo|bar), character classes (\w, \d, \s), and anchors (^, $) work as expected. Combine with `-i` for case-insensitive regex. Previously writing `zigrep "foo|bar"` would silently search for the literal seven-character string `foo|bar` instead
Release
Safety: edit with after=-1 (or any negative number) now returns 'after must be >= 0' instead of silently overwriting the entire file via the no-positioning fallback
Safety: edit rejects 'range' + 'after' together with a clear error - was silently dropping one based on internal precedence
Safety: 'lines' mode rejects line_from=0 with a clear error - line numbers are 1-indexed
Safety: dry_run now applies to all edit ops (was guarding only replace; delete/insert_after still dispatched)
Safety: contentFile arg must now resolve under the daemon's working directory - prevents reading arbitrary files outside the project (e.g. /etc/passwd, ssh keys) via this path
Stability: oversized commands (>1 MiB per line) now return 'command too large' and the daemon keeps running - was silently exiting and dropping every subsequent command in the connection
Stability: search and find walks now have a 64-deep cap - symlink cycles and recursive bind-mounts no longer hang until the watchdog timeout
Correctness: 'full' mode on small files with many short lines no longer silently truncates output - 105k-line files now return all 210k bytes (was capped at 1 MiB by line-number annotation overhead)
Correctness: 'full' mode response includes 'annotated:false' when the bypass path returns raw bytes - callers can detect that line numbers and the header are missing
Correctness: binary detection now samples head, middle, and tail of the file - files with a UTF-8 header (e.g. licence text) prepended to binary content are correctly classified as binary
Correctness: ls now uses lstat for symlink entries - reports the size of the link itself, not the target
JSON: binary-file error responses now properly escape paths containing backslashes, quotes, or control bytes - was producing invalid JSON that broke MCP clients
JSON: image responses now JSON-escape file paths - paths with special characters no longer break the response envelope
API: edit response surfaces a 'whole_file_replace' warning when no positioning is provided - makes the default behavior visible to callers
API: search rejects mutually-exclusive flag combinations (regex + word_boundary + case_insensitive) - was silently dropping all but one
API: edit response surfaces 'pattern_matches' count and 'pattern_matches_truncated' when a pattern matches multiple sites - was silently editing the first hit
Release
removed destructive 'replace' field from search and faster_search - was walking the entire path tree and rewriting every matching file in place, no opt-in, no dry-run, no backup. Search now rejects the field with a clear error pointing callers to edit/patch
edit with after=0 now prepends correctly - used to silently wipe the entire file via the default-replace fallback when op was not set to insert
patch with after=0 now prepends - used to error with 'patch requires range or after'
edit tolerates empty wrapper fields - sending empty range/pattern alongside a non-empty symbol no longer falls through to whole-file replace
pipe-mode batch flattens nested {tool, args:{...}} ops correctly - was MCP-only; pipe-mode batches now match the documented schema
batch search rejects 'replace' too - direct and batch paths are now consistent (was silently ignored in batch)
Safety: search refuses to walk system roots - /, /usr, /etc, /System, /Library, /var, /dev, /proc, /sys, /private/var, /Applications, /opt, /bin, /sbin, /nix, /snap
47 language type tags (was 24): PHP, Dart, C#, Scala, Haskell, OCaml, F#, Clojure, Erlang, Solidity, Vue, Svelte, Astro, GraphQL, Protobuf, Terraform, PowerShell, Make, Asm, R, Julia, Nim, Crystal, D, Perl, Groovy, VB, Objective-C, plus richer extension lists for C++, Python, Ruby, Markdown, JSON, CSS, Shell, SQL
regex_flavor validated: unsupported flavors like pcre now return a clear error instead of silently falling back to literal
symbol_search tool restored: codedb-snapshot-backed cross-project symbol lookup, ranked by frecency, with in-process snapshot cache
Zig 0.16.0 release line: local release builds now target the current Zig toolchain
62 regression tests covering destructive-path safety, after=0, range forms, UTF-8 encoding, batch serialization, symbol edges, and language type filters
Linux x86_64 build at v0.1.14: statically linked ELF, same feature set and fixes as macOS, runs on both glibc and musl distros
Release
20% faster reads on medium-to-large files - bulk-memcpy JSON escape cuts buffer operations by 10x
Safety scanning on every read: bidi overrides, invisible unicode, ANSI escapes, control chars - with structured warnings
SIMD fast path: 16 bytes per cycle, skips clean files entirely - safety scanning adds zero overhead for 99% of files
New search engine (ziggram): bigram index eliminates 90%+ of files before content scan, frecency ranking, background refresh
meta_search: generates multiple search variants (literal, regex, word-boundary) and merges results
faster_search: warmed per-root candidate index with literal seed extraction
Headless MCP: muonry works when spawned without a TTY - Docker, forge, CI all work now
zigedit CLI: standalone edit by symbol name, pattern match, or line range (291KB binary)
no_ignore flag: search inside node_modules, .git, dist when you need to
8MB stack savings: consolidated 9 separate 1MB buffers into one shared buffer per read
14 tools in the release: added zigedit, ziggram, zigtools, mcp-zip
Linux x86_64 binaries verified on real Ubuntu via Turbobox sandbox
Release
`muonry update` now works on Linux - was failing because install.sh requires bash but update invoked sh (dash)
Release
Linux support: all tools now ship as linux-x86_64 binaries - `curl install.sh | sh` works on Linux
macOS Intel support: darwin-x86_64 binaries for older Macs (runs via Rosetta 2 on Apple Silicon too)
4 platforms: darwin-arm64, darwin-x86_64, linux-x86_64 - all cross-compiled from Zig with zero dependencies
License gating verified on Linux: activation, offline tokens, and device binding all work
muonry MCP daemon works on Linux: initialize, read, search, edit, batch - full tool suite
Release hook: Linux binaries auto-build and upload to R2 after macOS release.sh completes
Release
Image viewing: mcp__muonry__read on PNG/JPEG/WebP/BMP returns an MCP image content block - multimodal agents see screenshots directly, zero subprocess
In-process JPEG compression via stb_image - ~4ms warm, cross-platform (macOS + Linux), replaces macOS-only sips
Size guard: skips JPEG re-encoding when PNG is smaller (wins for text/UI screenshots)
Binary file detection: null-byte probe prevents garbled output; non-image binaries return structured error with MIME type and size
zigrep: skip system/virtual dirs on root scans - /System, /Library, /Volumes, /private, /dev on macOS; /proc, /sys, /run on Linux - prevents 600%+ CPU on `zigrep pattern /`
MCP tool description updated to advertise image viewing to Claude, Codex, and any multimodal agent
Release
New lint tool: catch common Zig pitfalls before they bite - runs in-process, zero fork/exec
Telemetry: op recording wired correctly, flush reliability improved
Search fixes: improved match accuracy for edge cases
Device mismatch handling: clearer error messages for license issues
Release
Scope-aware edit: new 'pattern' param finds code and edits enclosing function in 1 call
Auto-diff: edit responses now include compact git diff - no follow-up diff call needed
Symbol cache: search with scope=true now caches symbols for faster subsequent edits
Batch auto-coalesce: same-file edits auto-reorder bottom-up to prevent line drift
20 regression tests covering all edit modes, batch, and new features
Release
telemetry sessions are now reliably flushed on shutdown
license validation handles device mismatch gracefully
Install email now includes the setup command before activation
Release
Telemetry data persists even if you force-quit - no more lost session stats
Usage stats are flushed periodically so the dashboard stays up to date
Pin to a specific version: `muonry update 0.1.0`
Hooks now prefer muonry MCP tools with zig* CLI as fallback
Install script supports version pinning via CODEGRAFF_VERSION
Release
Initial release of Codegraff Pro toolchain
muonry MCP daemon - all tools run in one process (~0.7ms per op)
Offline license validation - works without internet after activation
Usage dashboard with savings, speed, and cache stats
One-line install with automatic macOS compatibility fixes
Claude Code hooks: auto-route to fast tools, verify edits, log errors
9 tools: zigrep, zigread, zigpatch, zigcreate, zigdiff, zigmemo, zigpar, zigharness, muonry
Install the loop
Run the installer, then let Graff evolve the work while CodeDB maps the repo.
curl -fsSL https://codegraff.com/install.sh | sh