Files
newgrok/AGENTS.md
T
2026-08-14 06:36:57 +00:00

8.7 KiB

CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

What this repository is

This is not a Rust project. It is a CraftBukkit/Spigot-style patch workflow wrapped around xai-org/grok-build (the grok CLI/TUI, a 91-crate Rust workspace).

Upstream is a periodic one-way export of an xAI-internal monorepo — linear squashed Synced from monorepo commits, with SOURCE_REV naming the internal commit — and its CONTRIBUTING.md states that no external PRs or patches are accepted. Changes cannot be pushed back, and upstream re-drops the whole tree. So local changes live as replayable patches, exactly as CraftBukkit does against Mojang:

patches/ is the source. work/ is the build output.

The two-layer model — read this before editing anything

Path Tracked? What it is
patches/ yes The only source of truth. One .patch file per change.
scripts/, Makefile, upstream.rev, README.md yes The workflow itself and the pinned upstream SHA.
upstream/ no (gitignored) Pristine clone of the vendor repo. Never edit.
work/ no (gitignored) upstream@upstream.rev + patches/ applied. This is where you edit Rust code. Fully disposable.

Two rules follow, and violating either silently destroys work:

  1. Rust source edits go in work/, never in patches/. Patch files are generated output — hand-editing them is how you get a tree that no longer applies.
  2. make rebuild is the only exit from work/. make apply does git reset --hard + git clean -fdx. Anything in work/ that has not been committed and exported by make rebuild is gone.

Spigot mapping, if it helps: upstream/ ≈ the CraftBukkit clone, work/ ≈ the patched work dir, patches/CraftBukkit-Patches/, apply-patches.shapplyPatches.sh, rebuild-patches.shrebuildPatches.sh, upstream.revversions/*.json.

Commands

Run everything from the repo root via make (make help lists all targets). The scripts inject ~/.cargo/bin into PATH themselves, so cargo need not be on the interactive PATH.

make setup       # idempotent: rustup + pinned toolchain, dotslash/protoc
make apply       # upstream.rev + patches/ -> work/   (FORCE=1 to discard work/ changes)
make rebuild     # work/ commits above `base` -> patches/
make status      # pinned rev, patch count, commits in work/, dirty state
make update-dry  # preview an upstream sync, change nothing
make update      # re-pin upstream.rev and forward-port patches

Build and test — all of these operate inside work/:

make build       # debug binary -> work/target/debug/xai-grok-pager
make release     # optimised build
make check       # cargo check
make test        # PKG=<crate> to pick the crate; defaults to xai-grok-version
make clippy
make fmt
make run         # build + launch the TUI

Running a single test. make test is a thin wrapper; go through build.sh directly to pass a filter, since extra args are forwarded to cargo verbatim:

CARGO_CMD=test PKG=xai-grok-version ./scripts/build.sh test_fork_tag
CARGO_CMD=test PKG=xai-grok-pager-bin ./scripts/build.sh version_output_writer -- --nocapture

./scripts/build.sh also accepts arbitrary cargo flags (--release, --locked, -j2, …).

Daily loop

One commit in work/ == one patch file. The commit message becomes the patch title.

make apply
$EDITOR work/crates/codegen/.../foo.rs
cd work && git add -A && git commit -m 'Do the thing'
cd .. && make rebuild
git add patches/ && git commit -m 'Do the thing'

To amend, reorder, squash, or drop existing patches, use ordinary git — work/ is a real repo, and the base tag marks the boundary between upstream and ours:

cd work && git rebase -i base
cd .. && make rebuild          # patches/ is regenerated wholesale

Upstream syncs

make update fetches upstream, reports the new commits / SOURCE_REV delta / changed-file count, re-pins upstream.rev, replays patches/ on the new base, and re-exports on success. On conflict it stops mid-git am and prints the resolution steps — resolve it like a rebase (git status, fix markers, git add -A, git am --continue), then make rebuild from the root.

Conflicts here are the point of the model, not a defect: they mark exactly where an upstream change collided with ours instead of letting it vanish.

Safety rails

The scripts refuse rather than silently discard. When one fires, understand it before overriding:

  • make apply aborts if work/ has uncommitted changes.
  • make apply aborts if the commit count above base ≠ the number of files in patches/. Usually this means a forgotten make rebuild; it also fires when you deliberately add or delete patch files, and the check cannot tell the two apart.
  • make rebuild / make build abort while a git am is half-finished.
  • FORCE=1 (i.e. make apply FORCE=1) is the escape hatch for both apply guards — it means "discard work/ and replay patches/ as-is".

make apply's git clean -fdx deliberately excludes /target; preserving the incremental cache is the difference between a fast replay and a cold rebuild.

Patches are generated with --zero-commit --full-index --no-signature --no-stat -N. --zero-commit keeps the From <sha> line stable across rebases (otherwise every patch file churns on every replay); --full-index gives git am --3way blob hashes to fall back on when context drifts.

Upstream tree architecture (inside work/)

91 workspace members: crates/codegen/ (74 — the CLI crate closure), crates/common/ (11 — shared leaves), crates/build/ (1), prod/mc/ (1), and third_party/ (4 — a vendored Mermaid diagram stack).

Crate Role
xai-grok-pager-bin Composition root; produces the xai-grok-pager binary (shipped as grok)
xai-grok-pager The TUI — scrollback, prompt, modals, rendering. Also carries docs/user-guide/
xai-grok-shell Agent runtime + leader/stdio/headless entry points
xai-grok-tools Tool implementations (terminal, file edit, search, …)
xai-grok-workspace Host filesystem, VCS, execution, checkpoints

Constraints inherited from upstream:

  • The root Cargo.toml is generated — treat it as read-only. Edit per-crate Cargo.toml files instead. Note it also carries the [patch.crates-io] pin for the our-forks/async-openai git dependency.
  • Always target a specific crate (-p <crate>). Full-workspace builds are slow enough to be impractical here; build.sh enforces this by always passing -p.
  • Toolchain is pinned to Rust 1.94.0 by rust-toolchain.toml. Lint/format config: clippy.toml, rustfmt.toml at the tree root.
  • protoc is needed only by xai-grok-tools-api (for proto/grok-tools.proto). Resolution order is $PROTOC → walk up for bin/protocPATH. bin/protoc is a DotSlash wrapper that fetches protoc 29.3; setup.sh installs dotslash and falls back to the system protobuf-compiler, and build.sh sets PROTOC if the wrapper is unusable.

When touching upstream code, check the tests that already cover it — the shipped example patch (below) exists partly to demonstrate this failure mode.

Build cost

On this host (4 cores / 7 GB) a cold debug build of xai-grok-pager-bin takes ~11 min and work/target grows to ~24 GB; the binary is ~612 MB. cargo check and cargo build keep separate caches, so make check after a make build is not fast (~6 min cold). Avoid make clean and make distclean unless you actually need the space — both throw away that cache. Prefer per-crate commands while iterating.

Example patches

patches/ ships two patches, both tagged [EXAMPLE PATCH] in their commit messages, and both safe to delete:

  • 0001 modifies upstream Rust: adds FORK_NAME / fork_tag() to xai-grok-version and wires it into the pager's version line, so --version prints grok [newgrok] 1.0.3 (…). The tag is inserted after "grok " rather than appended, because main.rs's version_output_writer_preserves_channel_aware_contract asserts the line still ends with the channel label; and display_version itself is untouched because test_display_version_formatting_matrix pins its output.
  • 0002 adds a new file (FORK.md), demonstrating that file-creating patches work.

Deleting them requires the override, since work/ still holds their commits: rm patches/000*.patch && make apply FORCE=1.

License

Upstream code is Apache-2.0 (work/LICENSE); changes in patches/ are distributed under the same. This is an unofficial fork, unaffiliated with xAI.