Conversation
Add the official installer, put grok and agent on the guest PATH, and require the binary in the golden image. Marketplace baking comes later.
Parse api_key, env_forward, config_dir, marketplaces, plugins, and Model Context Protocol servers the same way [claude] and [codex] work.
Add coop grok, forward XAI_API_KEY, and copy host allowlisted files without following directory symlinks. Write managed settings and folder trust, drop the host [plugins] table, set a copied auth.json to 0600, and install configured plugins. coop agent update --grok runs grok update.
Add the integration guide and update the command, config, trust-model, and getting-started docs so the third agent is listed with Claude and Codex.
A developer ~/.grok/skills can hold gigabytes of git lore and venvs. Copying that into every VM start filled the Lima disk and left read-only packs that a second scp could not overwrite. The restart remove quoted ~ so it never expanded. Skip hidden and bare-git directories, leave ~/ unquoted in the guest remove, and isolate the integration suite from host ~/.grok.
Growing a disk with truncate left lima.yaml at the old size, so the next start looked like a shrink and Lima refused to boot. Update disk: with the grow, and revert the yaml if truncate fails.
| // A previous boot may have copied read-only files. scp cannot | ||
| // overwrite those; replace the dest directory first. | ||
| if let Some(name) = path.file_name().and_then(|n| n.to_str()) { | ||
| target.exec(remove_guest_staged_dir(guest_subdir, name))?; |
There was a problem hiding this comment.
Please preserve guest-only files when refreshing these directories. This shared helper also copies Claude rules/ and commands/ and Codex prompts/. If the host supplies one of those directories, restarting now deletes files created only in the guest; the previous recursive copy was additive. Removing the directory before transfer also leaves it missing or partially restored if SCP fails. Could the read-only-file handling preserve existing entries and avoid deleting the destination before a successful transfer?
| toml::Value::String("always-approve".to_string()), | ||
| ); | ||
|
|
||
| if root.remove("plugins").is_some() { |
There was a problem hiding this comment.
This removes guest plugin activation as well as imported host settings. bootstrap_grok calls this merge on every boot, even with config_dir = false, but installs plugins only on first boot and only for the delta missing from the image. In the inspected upstream implementation, installation writes [plugins].enabled, and discovery disables user/marketplace plugins absent from that list. Consequently, this loses activation on restart, or on first boot for Lima-baked plugins. Please preserve guest plugin state separately from the host table being imported. The upstream behavior is visible in installation/config handling and discovery; I did not verify an installed Grok artifact against that source revision.
| let disk_value = format!("\"{}GiB\"", new_size.as_u32()); | ||
| let edited = set_yaml_scalar(&original, "disk", &disk_value) | ||
| .with_context(|| format!("No top-level 'disk' key in {}", yaml_path.display()))?; | ||
| crate::fs_util::atomic_write_with_mode(&yaml_path, &edited, 0o644)?; |
There was a problem hiding this comment.
Please restore the original YAML when truncate cannot be spawned, too. This write happens before .status().context(...) ?, which returns immediately if the executable is missing or cannot run. The restoration below only handles a successfully spawned process returning a nonzero status, so a spawn failure reports an unsuccessful resize while leaving the enlarged disk setting persisted. Both failure paths should restore the original configuration.
| if coop_exec /home/ubuntu/.grok/bin/grok --version >/dev/null; then | ||
| pass "grok binary invocable via full path" | ||
| else | ||
| skip "grok --version" "binary exists but --version returned non-zero" |
There was a problem hiding this comment.
Please fail this check when an installed Grok executable cannot report its version. Provisioning already checks test -x, but that does not establish that the loader/runtime works. Skipping a failed --version allows an executable but unusable installation to pass this phase. The earlier missing-binary skip can remain for deliberately supported older images; this branch should distinguish an installed binary that fails to run.
| if curl -fsSL -o "$INSTALLER" https://x.ai/cli/install.sh 2>/tmp/grok-curl-err; then | ||
| break | ||
| fi | ||
| CURL_EXIT=$? |
There was a problem hiding this comment.
$? here is the status of the completed if, not the failed curl. An if with a false condition and no else returns zero, so these retry and final-error messages always report curl exit code 0. Please capture the failure status inside an else branch. An isolated Bash reproduction with a child exiting 22 returned 0 after the if, versus 22 inside else.
|
Thanks for contributing Grok Build support! The main changes I'd like to see are preserving guest-created config files and Grok plugin activation across restarts, restoring Lima's configuration on every resize failure path, failing the version check when an installed Grok binary cannot run, and reporting curl's actual failure status. I've left the details inline. |
Problem
coop can launch Claude Code and Codex in the guest. Grok Build has to be
installed and configured by hand.
Description
coop groklaunches Grok Build in the guest.coop setupinstalls it fromhttps://x.ai/cli/install.sh as the guest user. The image ships home skel
files as root, so setup
chown -Rs the guest home first. The launcherSSHes in with
--always-approve,--trust, and--cwd /workspace.--askadds--permission-mode default.loginandlogoutkeep--trustand--cwd /workspace.Changes
~/.grok/binon PATH,/usr/local/bin/grok,grok-yolo. The guest installers share oneshell; Grok deletes its temp installer after it runs.
[grok]:api_key,env_forward,config_dir, marketplaces,plugins, Model Context Protocol servers.
XAI_API_KEYgoes in over SSHSendEnv. Allowlisted hostfiles overlay into
~/.grok. Restart overwrites files still presenton the host; guest-only files and
config_dir = falsekeep priorcopies. Directory symlinks, hidden directories, and bare git repos
stay on the host. Host
config.tomlis merged except[plugins];guest
[plugins]is kept./workspaceis recorded intrusted_folders.toml. A copiedauth.jsonis mode0600.Configured plugins install on first boot.
coop agent update --grokrunsgrok update. The guest user can rungrok updatedirectly.--checkprints Claude Code, Codex, andGrok Build.
lima.yamldisk:andrestores the original yaml if the grow fails.
docs/grok-integration.md, commands, getting started, trustmodel, changelog.
--no-agentsnames Grok Build.grok-yolo, settings merge afterrestart,
--checknames all three. The suite sets[grok] config_dir = false. The merge phase pointsconfig_dirat afixture directory.
Existing images:
coop setup --rebuild. Existing VMs:coop restore <vm> --image <image> --reprovision(or destroy andrecreate).
Validation