add agents.md
This commit is contained in:
@@ -0,0 +1,165 @@
|
|||||||
|
# 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=<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:
|
||||||
|
|
||||||
|
```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 <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/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.
|
||||||
Reference in New Issue
Block a user