# 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`](https://github.com/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.sh` ≈ `applyPatches.sh`, `rebuild-patches.sh` ≈ `rebuildPatches.sh`, `upstream.rev` ≈ `versions/*.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`. ```sh 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/`: ```sh make build # debug binary -> work/target/debug/xai-grok-pager make release # optimised build make check # cargo check make test # PKG= 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: ```sh 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. ```sh 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: ```sh 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 ` 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 `).** 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/protoc` → `PATH`. `bin/protoc` is a [DotSlash](https://dotslash-cli.com) 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.