ragbox is the flagship tool here: local-first codebase memory for AI agents. Build a searchable semantic snapshot of your repo, query it from the terminal, and keep it local. Ollama-compatible, single binary, no vector DB server.
This repository is the engineering monorepo behind ragbox and a small set of macOS developer tools built on a reusable FASM runtime.
| Tool | Promise |
|---|---|
ragbox |
Local codebase memory for Codex, Claude, Gemini, and other AI agents |
machodoctor |
Explain why a macOS binary does not run |
fasm-mac |
Assembly/runtime foundation for x86_64 FASM tools on macOS |
Product page: https://kroq86.github.io/fasm-mac/
Use ragbox when ripgrep is too literal, a vector DB is too much machinery,
and you want a local semantic index your AI agent can query.
brew tap kroq86/fasm-mac https://github.com/kroq86/fasm-mac
brew install ragbox
brew install ollama
ollama pull nomic-embed-text
arch -x86_64 ragbox build --root . --out memory.lv
arch -x86_64 ragbox search --index memory.lv --query "where is auth handled?" --jsonOn Apple Silicon, ragbox runs through Rosetta (arch -x86_64). The index stays
in local files: memory.lv, memory.lv.manifest.json, optional refresh state,
and optional delta sidecar.
Why not the obvious alternatives?
| Alternative | ragbox difference |
|---|---|
ripgrep |
semantic search, not lexical search |
| vector DB server | copyable file snapshot, not a running service |
| RAG platform | local CLI for repo memory, not a web platform |
More: docs/ragbox.md. Release check:
scripts/check_ragbox_release.sh.
fasm-mac is also an experimental macOS bridge for flat assembler classic 1.73.35. The goal is practical CLI compatibility for small x86_64 fasm programs on macOS:
fasm file.asm
./fileOn Apple Silicon this runs through Rosetta. This is not a native arm64 rewrite of fasm classic.
fasm classic does not contain a Mach-O formatter. This project keeps the upstream fasm compiler core and adds a macOS pipeline around it:
- fasm emits ELF64 executable or ELF64 relocatable object output.
fasm/tools/elf64_to_macho64.pyconverts the supported ELF layout into Mach-O64.- macOS runs or links the resulting x86_64 Mach-O file.
That means this repository gives you a usable macOS command, not a new
upstream format Mach-O directive inside fasm.
brew tap kroq86/fasm-mac https://github.com/kroq86/fasm-mac
brew install fasm-macThen use fasm from anywhere:
fasm hello.asm
arch -x86_64 ./helloOn Apple Silicon, output binaries are x86_64 Mach-O and run through Rosetta.
Upgrade or remove:
brew upgrade fasm-mac
brew uninstall fasm-mac./install.shThe installer creates:
~/.local/bin/fasm -> <repo>/bin/fasm
Make sure ~/.local/bin is in your PATH:
export PATH="$HOME/.local/bin:$PATH"Build a runnable Mach-O executable, using the source basename as output:
fasm fasm/basic/fib.asm
./fasm/basic/fibBuild and run:
fasm run fasm/basic/fib.asmExplicit modes:
fasm --emit=macho file.asm [output] # Mach-O executable
fasm --emit=elf file.asm [output] # original ELF output
fasm --emit=macho-obj file.asm object.o # Mach-O object for clang/dylibDirectly call the bundled host fasm:
fasm host <args...>Runnable examples should include the platform layer instead of hardcoding Linux syscall numbers:
format ELF64 executable 3
include "fasm/core/platform.inc"
segment readable executable
entry start
start:
write_file STDOUT, msg, msg_len
exit 0
segment readable writeable
msg db "hello", 10
msg_len = $ - msgThe shim passes:
TARGET_OS=macosfor Mach-O outputTARGET_OS=linuxfor--emit=elf
platform.inc currently provides write_file, read_file, open_file,
close_file, exit, syscall helper macros, and the Darwin constants needed by
the reusable file, socket, stat, and directory-walk helpers.
Platform-agnostic helpers for format ELF64 executable 3. All assemble
without data-segment declarations and follow the System V AMD64 ABI.
| File | What it provides |
|---|---|
fasm/core/for.inc |
for reg, lo, hi / endfor reg — nestable register-based counted loop |
fasm/core/control.inc |
_if/_else/_endif, _while/_endw, _repeat/_until structured control flow |
fasm/core/mem.inc |
memcpy, memset, memcmp, memmove, memxor |
fasm/core/base64.inc |
base64_encode(rdi,rsi,rdx)→rax, base64_decode(rdi,rsi,rdx)→rax |
fasm/core/math_fp.inc |
fp_isnan, fp_isinfinite, fp_isfinite, fp_floor, fp_ceil, fp_fmod, fp_frexp |
fasm/core/eml.inc |
lb_eml_f64 — EML operator leaf exp(x)-log(y) (arXiv:2603.21852); export via eml_core.asm |
Examples:
fasm fasm/examples/elfexe/forloop64.asm /tmp/forloop64
fasm fasm/examples/elfexe/control64.asm /tmp/control64fasm struc defines memory layout at assemble time (field offsets and
sizes). Runtime growable vectors live in fasm/core/dynvec.inc
with a central fasm/core/heap.inc allocator and
mark-and-sweep gc_collect.
Runnable demo (prints [[1, 2], [3]]):
fasm fasm/examples/nested_list_demo.asm
arch -x86_64 ./fasm/examples/nested_list_demoSmoke test:
fasm fasm/tests/macos-smoke/nested_list.asm
arch -x86_64 ./fasm/tests/macos-smoke/nested_listLeetCode-style examples covering arrays, hash maps, linked lists, trees,
graphs, stacks, and dynamic programming. Several examples are intentionally
thin wrappers around reusable helpers in fasm/core.
scripts/check_leetcode_examples.sh| Command | Problem / approach | Output |
|---|---|---|
best_time_to_buy_sell_stock.asm |
LC 121 via dp.inc |
5 |
binary_search.asm |
LC 704 binary search | 4 |
climbing_stairs.asm |
LC 70 via dp.inc |
8 |
contains_duplicate.asm |
LC 217 int hash map | 1 |
first_unique_character.asm |
LC 387 character counts | 0 |
house_robber.asm |
LC 198 via dp.inc |
4 |
implement_queue_using_stacks.asm |
LC 232 via stack.inc |
1 1 0 |
intersection_of_two_arrays.asm |
LC 349 int hash map | 2 |
invert_binary_tree.asm |
LC 226 via tree.inc |
4 7 9 6 2 3 1 |
linked_list_cycle.asm |
LC 141 via listnode.inc |
1 |
majority_element.asm |
LC 169 Boyer-Moore vote | 2 |
maximum_depth_binary_tree.asm |
LC 104 via tree.inc |
3 |
maximum_subarray.asm |
LC 53 via dp.inc |
6 |
merge_sorted_array.asm |
LC 88 two pointers from end | 1 2 2 3 5 6 |
merge_two_sorted_lists.asm |
LC 21 via listnode.inc |
1 1 2 3 4 4 |
middle_of_linked_list.asm |
LC 876 via listnode.inc |
3 |
missing_number.asm |
LC 268 xor | 2 |
move_zeroes.asm |
LC 283 in-place compaction | 1 3 12 0 0 |
nested_list_weight_sum.asm |
LC 339 | 10 |
number_of_islands.asm |
LC 200 via grid.inc |
1 |
palindrome_linked_list.asm |
LC 234 via listnode.inc |
1 |
remove_duplicates_sorted_array.asm |
LC 26 in-place unique prefix | 5 0 1 2 3 4 |
reverse_linked_list.asm |
LC 206 | 5 4 3 2 1 |
search_insert_position.asm |
LC 35 lower bound | 2 |
single_number.asm |
LC 136 xor | 4 |
sort_array.asm |
LC 912 | -1 0 1 2 3 |
two_sum.asm |
LC 1 brute O(n²) | 0 1 |
two_sum_hashmap.asm |
LC 1 hash map O(n) | 0 1 |
valid_anagram.asm |
LC 242 character counts | 1 |
valid_parentheses.asm |
LC 20 via stack.inc |
1 |
Core libraries: base64.inc, control.inc, dirwalk.inc, dp.inc, file.inc, for.inc, grid.inc, hashmap.inc, hashmap_str.inc, hex.inc, json.inc, listnode.inc, macho.inc, math_fp.inc, mem.inc, scanner.inc, search.inc, stack.inc, tree.inc, sort.inc, str.inc, repl.inc, oop.inc (vtable + methods).
OOP-style demo (Playlist with append / print / reverse via vtable):
fasm fasm/examples/oop_playlist.asm
arch -x86_64 ./fasm/examples/oop_playlistExpected output: 3 1 4 1 5 then 5 1 4 1 3.
In-memory string-key store with a Redis CLI–style REPL (stdin/stdout, no TCP):
fasm fasm/apps/miniredis.asm
arch -x86_64 ./fasm/apps/miniredisCommands (v1.1): PING, SET key value, GET key, EXISTS key, DEL key, DBSIZE, INCR key, DECR key, MGET k1 k2 …, KEYS, SAVE path, LOAD path, QUIT, EXIT.
SET stores a signed int64 when the value parses as an integer; otherwise the raw token is stored as a string. GET prints ints, strings, or (nil) if missing. INCR/DECR require an int value (or create 1/-1 if the key is absent); strings return ERR wrongtype. MGET needs at least two key tokens (max 16 tokens per line). KEYS lists all keys (no pattern filter in v1). SAVE/LOAD use a line-oriented text dump (see below).
Limits: 256-byte lines, ASCII keys/values without spaces in v1, up to 16 tokens per REPL line.
Dump format (# miniredis v1 header):
# miniredis v1
I user 42
S greeting hello
I = int value, S = string value (remainder of line after the key token).
Example session:
miniredis> SET user 42
OK
miniredis> SET greeting hello
OK
miniredis> GET user
42
miniredis> GET greeting
hello
miniredis> INCR user
OK
miniredis> GET user
43
miniredis> SAVE dump.txt
OK
miniredis> LOAD dump.txt
OK
miniredis> DEL user
1
miniredis> GET user
(nil)
Pipe a script:
printf 'SET a 1\nGET a\nDBSIZE\nQUIT\n' | arch -x86_64 ./fasm/apps/miniredisSmoke tests: fasm/tests/macos-smoke/str_hash.asm, hashmap_str.asm, repl_ping.asm, miniredis_script.asm, tcp_echo.asm.
Tiny literal-search CLI inspired by grep/ripgrep. It searches one or more files
for a byte-exact literal and prints matching lines as path:line:text.
fasm fasm/apps/fscan.asm
arch -x86_64 ./fasm/apps/fscan [-c] [-l] [-i] needle file.txt other.txtHomebrew:
brew install kroq86/fasm-mac/fscan
fscan needle file.txtSmoke test:
scripts/check_fscan.shTiny native hex dump CLI for peeking at file bytes. It demonstrates the
reusable hex.inc formatter plus chunked file reads.
fasm fasm/apps/hexpeek.asm
arch -x86_64 ./fasm/apps/hexpeek [-n bytes] [-s skip] file.binHomebrew:
brew install kroq86/fasm-mac/hexpeek
hexpeek -n 64 file.binRelease packaging:
scripts/build-hexpeek-release.sh 0.1.0Smoke test:
scripts/check_hexpeek.shTiny native raylib raycaster maze game. It is an original Doom-inspired mini
game, not a Doom port: it does not ship Doom code, WADs, maps, sprites, sounds,
names, or trademarks. It demonstrates the reusable fixed-point
raycast.inc helpers plus the
ccall64.inc C ABI bridge for Mach-O objects.
brew install raylib
fasm --emit=macho-obj fasm/apps/raymaze.asm /tmp/raymaze.o
clang -arch x86_64 /tmp/raymaze.o $(pkg-config --cflags --libs raylib) -o raymaze
arch -x86_64 ./raymazeBecause current fasm-mac output is x86_64-only, the linked raylib must also be
x86_64. On Apple Silicon, the default /opt/homebrew raylib bottle is arm64;
use an Intel/Rosetta Homebrew raylib install for a real windowed build.
Snapshot mode for deterministic checks:
arch -x86_64 ./raymaze --snapshot snapshot.ppmRelease packaging:
scripts/build-raymaze-release.sh 0.1.0Smoke test:
scripts/check_raymaze.shSingle-threaded concurrent static HTTP server for macOS x86_64. It uses the
green-thread scheduler, kqueue, and nonblocking sockets: one slow or partial
client does not block other clients. Successful GET responses for regular
files use macOS sendfile.
fasm fasm/apps/httpmini.asm httpmini
arch -x86_64 ./httpmini --root ./public --port 8080 --bind 127.0.0.1V1 serves local regular files with GET and HEAD, closes each connection
after one response, serves /index.html for /, writes a simple access log to
stderr, and rejects directories, symlinks, % escapes, backslashes, and ..
path components.
Release packaging:
scripts/build-httpmini-release.sh 0.1.0Smoke test:
scripts/check_httpmini.shKafka-like local durable append-only message broker for macOS x86_64. It uses
the green-thread scheduler, kqueue, nonblocking sockets, and a length-prefixed
record log with a message-offset index and CRC32C per record. Topic data is
stored as rotated base-offset segments plus a global offset index; tune segment
size with --segment-bytes N. Accepted PRODUCE writes are fsync-backed, and
restart recovery trims segment/index tails back to the committed global offset
index. v1.3 uses a breaking storage/raw fetch format:
[u32_len][u32_crc32c][payload].
fasm fasm/apps/logbus.asm logbus
arch -x86_64 ./logbus --dir ./data --port 9092 --bind 127.0.0.1V1 commands use a RESP-like protocol: PING, PRODUCE topic payload,
FETCH topic offset max_bytes, FETCHBATCH topic offset max_bytes,
COMMIT group topic offset, OFFSET group topic, and QUIT.
FETCHBATCH returns raw [u32_len][u32_crc32c][payload]... log bytes via macOS
sendfile. This is a local single-partition broker, not a distributed Kafka
replacement.
Release packaging:
scripts/build-logbus-release.sh 0.1.0Smoke test:
scripts/check_logbus.shExperimental brew-worthy tool: batch snapshot index builder plus exact
cosine top-k search. logbus stays dumb; FASM owns f32 dot/norm/top-k only;
Zig wires protocol, files, ingest, and doc_id mapping (C++ host available in
fasm/apps/logvec/). v0 metric: cosine similarity
(score = dot / (norm(q)*norm(v)), higher is better). build-index
is one-shot — it does not tail topics. Spec: docs/logvec.md.
System form (Level 4): docs/system_form.md.
fasm --emit=macho-obj fasm/apps/logvec_core.asm logvec_core.o
zig build-exe fasm/apps/logvec.zig logvec_core.o \
-target x86_64-macos -mcpu=baseline -O ReleaseSafe -femit-bin=logvec
arch -x86_64 ./logvec search --index index.lv --query query.bin --top 5C++ host (same CLI, binary name logvec_cpp):
fasm --emit=macho-obj fasm/apps/logvec_core.asm logvec_core.o
clang++ -std=c++20 -O2 -arch x86_64 \
fasm/apps/logvec/logvec.cpp logvec_core.o -o logvec_cpp
arch -x86_64 ./logvec_cpp search --index index.lv --query query.bin --top 5Smoke test:
scripts/check_logvec.sh
scripts/check_logvec_cpp.sh
scripts/bench_logvec.sh # in-process top-k regression (1k/10k/100k × dim=768)
scripts/bench_perf.sh # layered dot/topk/search/io + parallel + ragbox breakdownv0.2 adds layered bench (--layer dot|topk|search|io), scalar vs AVX2 dot A/B,
parallel exact search (1–4 threads), and unit-vector top-k fast path. Exact
linear scan — ~4.5 ms for 10k×768 single-thread, ~1.4 ms with 4 threads (see
docs/logvec.md). Not ANN; agent-scale snapshots only.
Local-first codebase memory for AI agents: chunk a repo, embed via Ollama,
build a copyable .lv index + JSON manifest, and search it from the terminal.
One x86_64 binary — no Python venv, no vector DB server, no web platform. More:
docs/ragbox.md. System form (Level 4):
docs/system_form.md.
Homebrew:
brew tap kroq86/fasm-mac https://github.com/kroq86/fasm-mac
brew install ragbox
brew install ollama
ollama pull nomic-embed-text
arch -x86_64 ragbox doctor --skip-ollama
arch -x86_64 ragbox build --root ./repo --out memory.lv
arch -x86_64 ragbox refresh --root ./repo --index memory.lv
arch -x86_64 ragbox search --index memory.lv --query "where is auth handled?" --jsonWhy not the obvious alternatives?
| Alternative | ragbox difference |
|---|---|
ripgrep |
semantic search, not lexical search |
| vector DB server | copyable file snapshot, not a running service |
| RAG platform | local CLI for repo memory, not a web platform |
Manual build (from source):
fasm --emit=macho-obj fasm/apps/logvec_core.asm logvec_core.o
clang++ -std=c++20 -O2 -arch x86_64 -pthread \
fasm/apps/ragbox/ragbox.cpp logvec_core.o -o ragbox
arch -x86_64 ./ragbox build --root ./repo --out memory.lv
arch -x86_64 ./ragbox refresh --root ./repo --index memory.lv
arch -x86_64 ./ragbox search --index memory.lv --query "auth middleware" --jsonRelease packaging:
scripts/build-ragbox-release.sh 0.3.0
scripts/check_ragbox_release.shSmoke test:
scripts/check_ragbox.sh
scripts/check_ragbox_release.shOptional live check (Ollama required):
scripts/check_ragbox_live.shAI-native LLDB snapshot debugger for macOS binaries. Its useful surface is the CLI report mode: run a target once under LLDB batch mode and write a structured JSON file with status, exit code, crash signal, registers, backtrace, disassembly near the program counter, stack memory, Mach-O summary, and an escaped LLDB output tail.
fasm --emit=macho-obj fasm/apps/macdbg.asm /tmp/macdbg.o
clang -arch x86_64 /tmp/macdbg.o $(pkg-config --cflags --libs raylib) -o macdbg
arch -x86_64 ./macdbg --snapshot ./program report.json
arch -x86_64 ./macdbg --snapshot --args ./program arg1 arg2 -- report.jsonThe report is intended to be consumed by tools and agents:
{
"tool": "macdbg",
"mode": "snapshot",
"status": "exited",
"exit_code": 0,
"signal": null,
"registers": {"rip": "0x..."},
"backtrace": [],
"disasm": [],
"stack_memory": []
}There is also an experimental raylib snapshot viewer:
arch -x86_64 ./macdbg --ui ./program
arch -x86_64 ./macdbg --ui --args ./program arg1 arg2The UI is not a live step debugger yet. Press R to rerun the LLDB snapshot,
J to toggle the raw JSON/LLDB tail view, and Esc to quit. Because current
fasm-mac output is x86_64-only, the linked raylib must also be x86_64, just
like raymaze.
Release packaging:
scripts/build-macdbg-release.sh 0.1.0Smoke test:
scripts/check_macdbg.shTiny native recursive directory counter. It demonstrates the reusable
dirwalk.inc API for directory traversal, file type
detection, and stat64 size reads.
fasm fasm/apps/pathsum.asm
arch -x86_64 ./fasm/apps/pathsum [dir]Output:
files 2
dirs 1
bytes 1234
Homebrew:
brew install kroq86/fasm-mac/pathsum
pathsum .Release packaging:
scripts/build-pathsum-release.sh 0.1.0Smoke test:
scripts/check_pathsum.shStandalone macOS Mach-O inspector intended to ship as its own Homebrew formula
and ready-to-run binary. It is separate from fasm-mac; FASM is only used to
build release artifacts. Universal/fat Mach-O files are supported by inspecting
their x86_64 slice in v1.
fasm fasm/apps/machodoctor.asm
arch -x86_64 ./fasm/apps/machodoctor ./fasm/apps/machodoctor
arch -x86_64 ./fasm/apps/machodoctor --json ./fasm/apps/machodoctor
arch -x86_64 ./fasm/apps/machodoctor --deps ./fasm/apps/machodoctor
arch -x86_64 ./fasm/apps/machodoctor --check ./fasm/apps/machodoctorRelease packaging:
scripts/build-machodoctor-release.sh 0.1.0Smoke test:
scripts/check_machodoctor.shStandalone local release QA checker for Homebrew-style binary products. It validates one formula, one release tarball, and one built Mach-O binary before uploading release assets.
fasm fasm/apps/shipcheck.asm
arch -x86_64 ./fasm/apps/shipcheck Formula/hexpeek.rb dist/hexpeek-0.1.0-macos-x86_64.tar.gz ./hexpeekChecks include formula url basename, version, sha256, bin.install, the
tarball filename shape, and whether the binary is an x86_64 Mach-O executable.
Tar archive contents remain a shell-script smoke check in v1.
Homebrew:
brew install kroq86/fasm-mac/shipcheck
shipcheck Formula/hexpeek.rb dist/hexpeek-0.1.0-macos-x86_64.tar.gz ./hexpeekRelease packaging:
scripts/build-shipcheck-release.sh 0.1.0Smoke test:
scripts/check_shipcheck.shTiny structured log slicer for plain logs and JSONL. It is the first consumer
of the reusable line scanner in fasm/core/scanner.inc and the minimal JSONL
field matcher in fasm/core/json.inc.
fasm fasm/apps/logknife.asm
arch -x86_64 ./fasm/apps/logknife --contains timeout app.log
arch -x86_64 ./fasm/apps/logknife --jsonl --level error --count app.jsonl
arch -x86_64 ./fasm/apps/logknife --jsonl --field status=500 app.jsonlRelease packaging:
scripts/build-logknife-release.sh 0.1.0Smoke test:
scripts/check_logknife.shRESP/TCP server on port 6379 (macOS x86_64, one client at a time):
fasm fasm/apps/miniredis_server.asm
arch -x86_64 ./fasm/apps/miniredis_serverCommands: PING, SET, GET, QUIT (same semantics as REPL for values: int if parseable, else string).
Test with redis-cli (x86_64/Rosetta) or nc:
redis-cli -p 6379 PING
redis-cli -p 6379 SET foo bar
redis-cli -p 6379 GET foo
redis-cli -p 6379 QUITWithout redis-cli:
printf '*1\r\n$4\r\nPING\r\n' | nc localhost 6379TCP echo smoke (port 9999):
fasm fasm/tests/macos-smoke/tcp_echo.asm
arch -x86_64 ./fasm/tests/macos-smoke/tcp_echo &
printf 'hi' | nc localhost 9999scripts/check_leetcode_examples.shBuild a Mach-O object and link it into a .dylib:
fasm --emit=macho-obj add.asm add.o
clang -arch x86_64 -dynamiclib wrapper.c add.o -o mylib.dylibOn Apple Silicon, Python ctypes examples need an x86_64/Rosetta Python to
load that dylib. An arm64 Python cannot load an x86_64 library.
- Output is x86_64 only.
- Native arm64 fasm classic is out of scope.
- The executable converter supports simple ELF64 executable layouts.
- The object converter supports simple allocatable
.text,.data,.bsssections and symbols. - ELF relocations in object files are rejected for now.
- fasm classic still does not understand
format Mach-O. - Coroutines and other callback/stack-switching examples need separate ABI review before being called supported on macOS.
The checked-in bridge expects the macOS x64 host binary at:
fasm/build/out/macos-x64/fasm-macos-x64
Rebuild it with:
./fasm/build/macos-x64.shVerify:
file fasm/build/out/macos-x64/fasm-macos-x64
arch -x86_64 fasm/build/out/macos-x64/fasm-macos-x64fasm fasm/basic/fib.asm
arch -x86_64 ./fasm/basic/fib
fasm --emit=elf fasm/basic/fib.asm /tmp/fib.elf
file /tmp/fib.elf
fasm --emit=macho-obj /path/to/add.asm /tmp/add.o
file /tmp/add.o- Original project: https://flatassembler.net/
- Upstream archive used here:
fasm-1.73.35.tgz
The original license is kept at fasm/license.txt.
- https://flatassembler.net/ — flat assembler (fasm1) by Tomasz Grysztar
- https://2ton.com.au/ — HeavyThing x86_64 FASM library by Jeff Marrison (GPLv2+); algorithms in
mem.inc,base64.inc,math_fp.incadapted from here - https://www.agner.org/optimize/ — Agner Fog's optimization guides and asmlib; small-copy and memcmp patterns
- https://board.flatassembler.net/ — FASM community board; macro techniques and fasm1 idioms
- https://github.com/tgrysztar/fasmg — fasmg by Tomasz Grysztar;
control.incstructured-flow macros inspired bypackages/x86/include/macro/if.inc