Repository navigation
refactor(cli,mcp): port the CLI and MCP server from C to Zig - #163
Merged
Merged
Conversation
Replace src/cli/{cli,hook_augment,progress_sink}.c and
src/mcp/{mcp,index_supervisor}.c with Zig modules in libcbm_zig. The C
headers (cli.h, progress_sink.h, mcp.h, index_supervisor.h) stay the
ABI: each Zig module exports the same symbols, and cbm_zig.zig checks
every pub cbm_* export against its translated header declaration, so a
signature that drifts from its header fails the build.
The two modules call into each other, so they move together:
- src/cli: cli.zig, commands.zig, archive.zig, store.zig, tool_args.zig,
hook_augment.zig, progress_sink.zig.
- src/mcp: mcp.zig (JSON-RPC, tool registry, arguments, server object,
store resolution), server.zig (dispatch, compact output,
detect_changes, session auto-index and update check, request handler,
stdio loop), search_tools.zig, code_tools.zig, graph_tools.zig,
project_tools.zig, index_tools.zig, index_supervisor.zig.
Behavior differences from the C code:
- search_code sorts its hits (by file, then by score) with a stable
sort; qsort left the order of ties unspecified.
- get_architecture frees scope_path when the store fails to open; the C
code leaked it.
- An unreachable enrich_connected helper and the always-NULL
alternatives parameter of build_snippet_response are not ported.
- A JSON-RPC request with no method gets "Method not found"; the C code
dereferenced NULL.
- Request durations use cbm_now_ns() (monotonic) instead of
clock_gettime.
Build and audit wiring: Makefile.cbm and build.zig drop the C sources
and list the Zig files; cbm_zig_c.h gains the headers the ported code
calls. security-audit.sh and its allowlist name the Zig files in place
of cli.c and mcp.c; the MCP file-read audit now counts src/mcp/*.zig
(18 reads, all path-contained or transport reads). Test and smoke
scripts that grep the old C files now grep the Zig files.
Net change: -3,536 lines (src/cli -1,700, src/mcp -1,909).
Signed-off-by: ata-sesli <atasesli@protonmail.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What does this PR do?
Ports the CLI (
src/cli) and the MCP server (src/mcp) from C to Zig. These were the last two large C modules on the Zig port list. They call into each other, so they move together.The C headers do not change.
cli.h,progress_sink.h,mcp.handindex_supervisor.hremain the ABI. Each Zig module exports the same symbols, andcbm_zig.zigchecks every exportedcbm_*function against its header declaration at compile time. A signature that drifts from its header fails the build.src/cli/cli.c,hook_augment.c,progress_sink.c(6,206 lines)src/cli/{cli,commands,archive,store,tool_args,hook_augment,progress_sink}.zig(4,506 lines)src/mcp/mcp.c,index_supervisor.c(9,220 lines)src/mcp/{mcp,server,search_tools,code_tools,graph_tools,project_tools,index_tools,index_supervisor}.zig(7,311 lines)Net change: −3,536 lines.
Behavior differences
search_codesorts hits (by file, then by score) with a stable sort.qsortleft the order of tied hits unspecified.get_architecturefreesscope_pathwhen the store fails to open. The C code leaked it.methodgets "Method not found". The C code dereferenced NULL.cbm_now_ns()(monotonic) instead ofclock_gettime.enrich_connectedhelper, and thealternativesparameter ofbuild_snippet_response, which every caller passed as NULL.Build and audit wiring
Makefile.cbmandbuild.zigdrop the C sources and list the Zig files.scripts/check-build-sources.shpasses.cbm_zig_c.hadds the headers the ported code calls.security-audit.shandsecurity-allowlist.txtname the Zig files instead ofcli.candmcp.c.src/mcp/*.zig, and its limit is 18 reads, up from 13. Reviewers should check this:mcp.calone already had 19 matching lines, andindex_supervisor.cwas never counted. All 18 are path-contained reads or transport reads.cli.callowlist justification ("sha256 checksum") was stale. The call it covers is the latest-releasecurllookup, and the new entry says so.Verification
Checks run on macOS arm64:
mcpsuite passed 176 tests, the same count as the earlier p119 baseline run. Theclisuite passed 132. Both ran throughscripts/zova-run-tests.sh.libcbm_zig.abuilds for native, x86_64-linux-gnu, aarch64-linux-gnu, x86_64-windows-gnu and aarch64-macos.zig fmt --check,scripts/check-build-sources.shandscripts/security-audit.shpass.Not run:
make -f Makefile.cbm test);lint-ci;smoke-test.sh;Checklist
git commit -s) — required, CI rejectsunsigned commits (DCO, see CONTRIBUTING.md)
make -f Makefile.cbm test): only themcpandclisuites were runmake -f Makefile.cbm lint-ci): not run