Add a Grok Build harness - #46
Merged
Merged
Conversation
A build target names both the stage and the agent it installs, so the value only ever reaches that one install step. A name per harness read as a knob per harness, and every new one added another. SWARMFORGE_HARNESS_INSTALL_BUST replaces OPENCODE_INSTALL_BUST and CLAUDE_INSTALL_BUST; `make update_opencode` and `make update_claude` are unchanged from the outside, and an override under an old name is ignored.
Add containerized support for xAI's Grok Build CLI, mirroring the Claude pattern: a persistent credentialed home, the harness's native skills dir, and the stable repo-slug mount path. - Dockerfile: install the official CLI via x.ai/cli/install.sh in a `grok` AGENT branch, relocate the binary to /usr/local/bin/grok, drop the root-side ~/.grok so the runtime config dir stays credential-only, and add a grok-runtime stage. - Makefile: build_grok/update_grok/run_grok/stop_grok targets and the matching image/home/args vars; config dest ~/.grok with reset disabled so credentials persist across runs. - entrypoint: deliver shared skills to Grok's native ~/.grok/skills and exclude skills/commands plus the host installer artifacts (bin/downloads/completions) from the layered config merge. Rename the repo-slug mount knobs to SWARMFORGE_REPO_SLUG / SWARMFORGE_REMOTE_NAME so every persistent-home harness shares them without coupling Grok to Claude.
Add a Grok Build section to the README: the install, the persistent ~/.grok home, AGENTS.md discovery, skills delivery, and config layering. A third harness also makes the existing prose wrong wherever it named two. Point those at every run_* target instead of enumerating, and give the shared-asset destinations a Grok entry.
A session with an mcp-interface tong refused to launch under run_grok because no MCP config emitter existed for the harness. Emit the discovered servers as Grok's native TOML shape ([mcp_servers.<name>] with a url key selecting the remote transport) and deliver them through the existing SWARMFORGE_TONG_MCP_FILE mount. Grok's config dest is its persistent home rather than a dir rebuilt each run, so merge_grok_mcp keeps the generated servers in a sentinel-delimited managed block: rewritten every run, stripped when a session has no MCP tongs, and yielding to a same-named server the user defines themselves (appending it would be a TOML duplicate-table error). The entrypoint's tong merge is now dispatched per harness, which also stops the fragment from being copied into an opencode.json inside a non-OpenCode config dest.
Note the managed config.toml block, why it exists, and that a user-defined server of the same name wins.
Docker's TTY default is TERM=xterm, so Grok hides truecolor themes and diffs quantize onto a tiny ANSI palette. `-e TERM -e COLORTERM` copies the host values through docker's passthrough, which reads run-anvil's environment; the same env make inherited from the launching shell.
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.
Adds xAI's Grok Build CLI as a third harness, alongside OpenCode and Claude Code.
What's here
build_grok/run_grok/update_grok/stop_grok. The image installs the official CLI viax.ai/cli/install.shin agrokAGENTbranch and relocates the binary to/usr/local/bin/grok, dropping the root-side~/.grokso the runtime config dir stays credential-only.Persistent credentialed home, the Claude pattern.
$(GROK_HOME_DIR)mounts at/home/anviland keeps~/.grok/across runs.~/.grok/skillsand~/.grok/commandsare tmpfs masks over it, so the entrypoint repopulates them per run and per-repo assets never accumulate in the persistent home or leak between repos.MCP tongs. A session with an
mcp-interface tong previously refused to launch underrun_grok, because no MCP emitter existed for the harness. The discovered servers are now emitted in Grok's native TOML shape —[mcp_servers.<name>], where aurlkey is what selects the remote transport — and delivered through the existingSWARMFORGE_TONG_MCP_FILEmount.Grok's config dest is its persistent home rather than a directory rebuilt each run, so
swarmforge/config/merge_grok_mcp.pykeeps the generated servers in a sentinel-delimited managed block: rewritten every run, stripped when a session has no MCP tongs, and yielding to a same-named server the user defines themselves (appending it would be a TOML duplicate-table error). The entrypoint's tong merge is now dispatched per harness, which also stops the fragment from landing in anopencode.jsoninside a non-OpenCode config dest.Two renames this pulls in
CLAUDE_REPO_SLUG/CLAUDE_REMOTE_NAMEbecomeSWARMFORGE_REPO_SLUG/SWARMFORGE_REMOTE_NAME. Both persistent-home harnesses use them, and neither should have to name Claude to do it. No fallback from the old names — an override under one is silently ignored, as with theOPENCODE_UID/OPENCODE_GIDdrop.OPENCODE_INSTALL_BUSTandCLAUDE_INSTALL_BUSTcollapse into oneSWARMFORGE_HARNESS_INSTALL_BUST(first commit, so the Grok work uses it rather than adding a third). A build target names both the stage and the agent it installs, so the value only ever reaches that one install step; a name per harness was restating the target, and every new harness added another.make update_opencodeandmake update_claudeare unchanged from the outside.Not in scope
Subagent definitions are not translated for Grok — the unified-agent pipeline still covers OpenCode and Claude only, and the entrypoint's
prepare_unified_agentsfalls through for the harness. Skills and commands travel the shared asset pipeline as usual.