Skip to content
,

Grok Build project loop: explore, change, check

9 min read
Grok Build project loop: explore, change, check, with the official product logo. Editorial illustration for Analytics Made Simple.

The warehouse scanner rejected 327 rows from shipments_aug18.csv at 8:12 a.m. Every bad cell looks like 08/18/26. The contract on the dock is 2026-08-18. You open Grok Build and type “make the export work.” Fourteen files change. The Dockerfile picks up a new base image. A logger grows extra fields. format_ship_date still prints a two-digit year with slashes. The next scan rejects 327 rows again.

This is Part 17 of the Grok series. Part 16 got the grok binary onto a sandbox machine. Now we use it without letting the agent redecorate the repo. The loop is explore, change, check. If you still mix chat tabs with a folder agent, keep the four Grok surfaces nearby.

UI labels move. Re-check the Grok Build overview the week you teach this to a teammate. Headless grok -p can run the same words. It will not make a sloppy prompt safer.

A four-beat project loop you can run

  • A four-beat project loop you can run in one sitting: ask, explore, small diff, check
  • How @ file mentions keep the agent in the room you meant
  • Prompt shapes that change one function instead of fourteen files
  • What “check” means: run something, open the diff, keep or restore with git
  • A worked toy for ship_date with before and after Python and a three-row result table

The loop on one card

Grok Build is useful when you already have a folder and a specific mess. It is a poor “do my job” button. The 327-row reject is a specific mess. “Make the export work” is not a loop. It is a wish.

Use four beats, in order:

  1. Ask with a boundary. Name the symptom, the file you suspect, and what the agent must not touch.
  2. Explore before any edit. Have it list call sites, print the current function, and quote the scanner contract. No writes.
  3. Change one thing. One function, one format string, one test. Plan mode if the agent wants a tour.
  4. Check. Run the toy. Open the diff. Restore anything extra. Then stop or start a new loop.
Grok Build loop: ask with a boundary, explore with at-files, change one thing, then run and read the diff.
Grok Build loop: ask with a boundary, explore with at-files, change one thing, then run and read the diff.

Skip explore and you get the 14-file patch. The model is trying to be helpful. Helpful, unscoped agents rewrite logging “while they are here.” Your review budget at 8:12 a.m. is not 14 files. It is one function and a three-row printout.

Git still sits under the loop. Commit or stash before you start if the branch already has other work. If the agent goes wide, git restore on the extra paths is faster than arguing in the TUI. Rollback is git. The next part in this series spends more time on that. Tonight, treat a clean status as part of “check.”

Explore with @ files

The TUI lets you point at a path with @. Official first-run examples look like @src/main.rs Walk me through this file. Same idea in a Python export folder: name the file, then ask a question that does not require a write.

Good explore prompts are nosy and small.

@exports/csv_writer.py Find every function that writes ship_date.
Quote the current format string.
List other files that call format_ship_date.
Do not edit anything.

That prompt does four jobs. It pins the file. It names the function. It asks for callers so you learn whether the bug is local. It forbids edits. If the answer says “callers are only write_shipments_csv in this same file,” you have a one-file change. If the answer says eight packages import it, you still change one function, but you plan a wider check.

Bad explore prompts hand the agent a mood.

This export is a mess. Clean it up so warehouse stops yelling.
Also tidy anything that looks old.

“Tidy anything that looks old” is how Dockerfiles move. The scanner does not care about your base image. The scanner cares about YYYY-MM-DD.

Explore questions that stay read-only: where is ship_date written, what is the format string, who calls it, what must stay untouched.
Explore questions that stay read-only: where is ship_date written, what is the format string, who calls it, what must stay untouched.

If the repo is larger than one file, keep explore in plan mode. /plan plus “no file edits until I approve” stops the agent from “fixing” while it reads. Shift+Tab cycles modes in the TUI. Use ask/watch permissions on a morning when 327 rows are already wrong. Auto-approve is for a later day, on a folder you trust, after this loop is muscle memory.

Read the explore answer out loud. If you cannot point at a single function after that answer, you are not ready to change code. Ask again. Attach another @ file. Do not reward a vague map with “ok, implement.”

Change one thing

Once explore names format_ship_date, the change prompt should be almost boring.

@exports/csv_writer.py Change format_ship_date so it returns YYYY-MM-DD.
Do not change logging, Docker, or other modules.
Do not add dependencies.
Show the diff for this file only.

Notice what is missing. There is no “improve readability.” There is no “while you are in there.” There is no “use best practices.” Those phrases are permission slips for extra files.

If the agent proposes a helper module, a new date library, and a config flag, say no. The scanner contract is a format string. A format string does not need a platform. You can add tests after the function is right. You can restyle the file in a second loop if you still care at lunch.

One change also means one commit later. Mixed commits (date fix + logger + Docker) are how the 14-file disaster lands in main because someone reviewed the date line and missed the base image.

Check: run, test, open the diff

A green-looking TUI message is not a check. Check is something you can see without trusting the model’s summary.

  • Run the function on three known dates and print the strings
  • If the repo has tests, run the narrow file, not the whole suite first
  • Open git diff yourself. Count files. If the count is not 1, stop
  • Restore extra paths. Keep the one hunk you asked for

A check prompt you can paste after the edit:

Run a three-row toy for format_ship_date using
2026-08-18, 2026-08-19, and 2026-01-05.
Print input, output.
Do not write more files.
Then stop.

Then leave the TUI (or open a second terminal) and run git yourself:

git status
git diff --stat
git diff exports/csv_writer.py

If git diff --stat lists 14 paths, the loop failed even if the date string is now correct. Restore the extras. The date fix can stay. The Dockerfile does not get a free ride because the model was “already in the repo.”

Headless note: grok -p "make the export work" is the same wish, with fewer chances to say no. Do not move this loop to CI until the prompt names a file, forbids extra writes, and you have a test that fails on 08/18/26.

Worked toy: format ship_date

Here is the whole bug in one function. Warehouse DB already stores ISO dates. The writer converts them to a US short date because someone once opened the CSV in Excel and wanted slashes. The scanner at the dock is not Excel.

Before:

from datetime import datetime

def format_ship_date(value):
    """value arrives as YYYY-MM-DD from the warehouse DB."""
    parsed = datetime.strptime(value, "%Y-%m-%d")
    return parsed.strftime("%m/%d/%y")

samples = ["2026-08-18", "2026-08-19", "2026-01-05"]
for raw in samples:
    print(raw, "->", format_ship_date(raw))

What that prints (the 327-row morning):

inputbeforescanner
2026-08-1808/18/26reject
2026-08-1908/19/26reject
2026-01-0501/05/26reject

After. Same function, one format string. No new package. No extra files.

from datetime import datetime

def format_ship_date(value):
    """Scanner contract: YYYY-MM-DD only."""
    parsed = datetime.strptime(value, "%Y-%m-%d")
    return parsed.strftime("%Y-%m-%d")

samples = ["2026-08-18", "2026-08-19", "2026-01-05"]
for raw in samples:
    print(raw, "->", format_ship_date(raw))

What that code prints after the one-line change:

inputafterscanner
2026-08-182026-08-18accept
2026-08-192026-08-19accept
2026-01-052026-01-05accept

Yes, the “after” function parses ISO and writes ISO. That looks silly until you remember the before version existed to please a human in Excel. If you still need a slash column for a person, add a second field later in a second loop. Do not smash both needs into one column and then ask the agent to “make everyone happy.”

A full first session on this toy, in order:

  1. Copy the before function into ~/sandbox/warehouse-export-toy/exports/csv_writer.py.
  2. cd there. git add and commit so you have a restore point.
  3. Start grok. Stay on ask/watch. Use plan mode if the agent gets chatty.
  4. Paste the explore prompt with @exports/csv_writer.py.
  5. Paste the one-function change prompt.
  6. Run the three-row script. Compare to the after table.
  7. git diff --stat. One file. If not, git restore the extras.

That is the whole skill. The 14-file version feels faster for thirty seconds. Then you spend the morning unscrewing a logger.

Ask with a boundary

MistakeWhat you getFix
Skip explore14-file “cleanup” around a one-line bugRead-only map first, then one change
“Tidy anything old”Dockerfile and logging in the same diffName the function. Forbid other paths
Trust the TUI summaryMissed extra filesgit diff --stat in your own terminal
Check only on the happy dateJanuary still serializes wrongThree rows, including an early month
Headless wish on CISame mess, no one watchingKeep grok -p off this job until the test exists

Ask with a boundary (check)

Rebuild the toy folder from Part 16. Drop in the before function. Run the loop once without letting the agent leave csv_writer.py. If you already have a real export bug, do explore only on that repo today. Change tomorrow, after you can name the function in Slack without opening the file.

The next part in this series is Grok Build tools, skills, and agent workflows. That is where AGENTS.md, skills, plugins, MCP, and subagents start to matter. Learn the loop first. A pile of extra tools on top of “make the export work” is how nine MCP servers join a date-format ticket. Index: Grok series.

Ask with a boundary 3

  • Ask with a boundary. Explore with @ files. Change one thing. Check with a run plus git diff
  • Forbids are part of the prompt: no logging, no Docker, no extra modules
  • A three-row printout beats a confident paragraph in the TUI
  • If git diff --stat is not one file, restore the extras before you continue
  • Save headless grok -p for a prompt that already survived this loop in the TUI

Sources

Research and further reading used for this article: