An agent opens the router, searches for the service, reads the same interface, then repeats the sequence in the next iteration. The loop looks busy, but much of the work is repository orientation. On a large codebase, that repeated scan can consume more attention than the edit itself.
The goal is not to stop Ralph from reading source. Current source is the final authority. The goal is to stop Ralph rereading repository roots when a smaller, verifiable context slice would answer the task. That requires an index with provenance, scoped queries, durable findings, and clear reasons to fall back to a full scan.
Before You Optimize the Loop
Before you try to stop Ralph rereading repository roots, confirm which loop you are running. Geoffrey Huntley’s original Ralph pattern describes an outer loop driven by a plan and executable feedback. The snarktank implementation launches a new Amp or Claude process for each iteration. Anthropic’s official plugin continues through a Stop hook inside the current Claude Code session. These reset boundaries create different reasons for repeated scanning.
Then measure the behavior. Record which files and directories are opened per iteration, which searches recur, how often review finds a missed consumer, and whether the active task actually changed. A repeated read can be correct after a commit or branch change. It is wasteful when the repository state is unchanged and the agent is reconstructing the same verified relationships.
This baseline turns coding agent repeated scanning into an observable retrieval problem. Optimize only the repeated orientation steps whose repository state and answer remained unchanged.
Do not optimize by injecting a full repository summary into every prompt. Summaries drift, hide uncertainty, and can be larger than the discovery they replace. Define the target instead: the smallest source-backed context that lets an iteration locate the owner, understand affected relationships, respect write scope, and choose the right checks.
Build a Module and Dependency Map
Start with a lightweight map of modules and boundaries. This reduces coding agent repeated scanning by preserving only the orientation facts that can be checked against the active revision. For each module, capture its path, public entry points, owned symbols, direct dependencies, primary consumers, and associated tests. Add generated or schema-derived surfaces only if the task can affect them. Every item should point back to a file and commit, not merely repeat an architectural label.
The map does not need to model every runtime behavior. It needs to answer common orientation questions reliably. A package index plus import graph may be enough for a conventional service. A monorepo with generated clients, dependency injection, and cross-language schemas may need symbol, call, and generation edges.
Queries such as “Stop Ralph rereading repository Reddit” usually express frustration with the symptom, not a request for a particular cache. The implementation choice should follow observed failure modes. If the loop repeatedly forgets module ownership, build an ownership index. If it misses indirect consumers, model dependency and call relationships. If it reruns the same commands, fix the task handoff or repository instructions.
Text search stays in the workflow. ripgrep is deterministic and line-oriented. By default it respects ignore rules and skips hidden and binary files. An index should complement that retrieval model by representing relationships; it should not be sold as a repair for imaginary randomness.
Query by Task Instead of Repository Root
Translate the acceptance criteria into retrieval questions before opening directories. A search such as “Stop Ralph rereading repository Reddit” names a symptom; the task query still needs to name the owner, behavior, and evidence required. For “add retry handling to outbound billing calls,” ask which module owns the client, which entry points call it, where retry policy is configured, and which tests exercise failure responses. Begin with those results and expand only when current source exposes another dependency.

A task query should include the active commit, allowed write paths, and expected behavior. Results should include file, symbol, relationship type, provenance, and confidence or limitations. The agent then opens the cited source and confirms that the path still exists and the relationship means what the task assumes.
Graphify is one possible codebase graph layer for this retrieval step. It may help return a task-sized subgraph containing modules, dependencies, definitions, and tests. It is not necessary for every repository, and it should not replace exact search, directory inspection, or executable checks. A simple module manifest may be the better tool when repository structure is already explicit.
Keep results small. Ranking twenty likely files can be useful; dumping thousands of graph nodes recreates root-level scanning in another format. Prefer a staged query: owner and entry point first, direct dependents second, tests and generated surfaces third, broader traversal only after evidence shows it is required.
Persist Useful Findings Between Iterations
Persist findings that are expensive to rediscover and likely to remain relevant for the active task. Examples include the verified owner module, the actual entry point behind an alias, required tests, an unexpected generated artifact, and a rejected path with evidence. Attach the commit and source locations so the next loop can check freshness.
Keep that task handoff separate from durable project rules. In snarktank’s implementation, the prompt tells the agent to read Git history and progress.txt, work on one story, run checks, commit, and append useful information. Its README says progress.txt resets for a new branch. Those file semantics are specific to snarktank, but the broader principle is portable: active findings need a lifecycle tied to the task.
Project-wide commands and conventions can live in scoped instructions such as AGENTS.md, whose specification allows directory-level rules. Do not promote a one-off discovery into permanent guidance without review. Derived graph facts should remain read-only to the loop and be refreshed from source rather than manually rewritten.
A useful handoff is short enough to inspect. Label verified facts, hypotheses, failed attempts, and pending checks. Archive the longer event history if audit requires it, but do not force every iteration to reread it.
Risks, Drift, and Review Habits
Caching the wrong fact makes the loop faster in the wrong direction. Invalidate module and graph results when the commit, branch, index schema, generated code, or dependency lock state changes in a relevant way. If provenance cannot be compared with the active checkout, retrieve again from current source.

Access boundaries matter as much as freshness. A shared index may expose code or paths outside an agent’s task. Apply repository permissions to retrieval, and keep write scope independent from read access. A result that mentions another module is not permission to edit it.
Reviewers should request a retrieval trail for high-impact changes: initial task query, source files opened, edges followed, excluded paths, tests selected, and assumptions left unresolved. The purpose is not surveillance. It is to distinguish a safe narrow search from a narrow search that simply missed the real consumer.
Use full rescans deliberately. They are appropriate after major refactors, branch switches, index corruption, uncertain generation pipelines, or evidence that scoped retrieval produced false negatives. They are also useful as periodic audits. The optimization succeeds when broad scans become evidence-driven exceptions, not when they disappear.
Finally, compare the indexed path with a baseline on representative tasks. Look for missed consumers, stale facts, unnecessary context, and review corrections. Do not publish a universal speed or token claim from a small internal sample.
FAQ
What should not be cached?
Do not cache secrets, volatile runtime values, unverified hypotheses presented as facts, or structural results without provenance. Avoid making generated output authoritative when its source schema is available. Short-lived test failures can be recorded in task state, but they should expire when the environment or commit changes.
How should teams test retrieval quality?
Build a set of real repository tasks with known owners, consumers, tests, and edge cases. Compare scoped retrieval with source inspection and review findings. Track false negatives, stale results, irrelevant context, and how often the agent must broaden the query. Re-run the set after index or repository changes.
When should a full rescan happen?
Rescan after a major branch or commit change, structural refactor, index-version change, generation update, or evidence that returned relationships are incomplete. A full scan is also justified when the task crosses unfamiliar boundaries or affects security, migrations, or a public interface whose consumers are uncertain.
What is the Ralph loop in Claude Code?
Anthropic’s Ralph Loop plugin uses a Stop hook to keep the same prompt active until a completion condition or iteration limit is reached. It operates inside the current Claude Code session. That differs from shell implementations that launch a new process for every iteration, so context and persistence behavior should be documented separately.
Conclusion
To stop Ralph rereading repository roots, first identify the repeated orientation question. Build only the module, dependency, or test map needed to answer it. Query by task, open the cited source, persist verified findings for the active scope, and invalidate them when repository state changes.
The result should be a more disciplined reading path, not less verification. Text search, source inspection, type checks, tests, and review remain the backpressure that keeps a loop honest. For a deeper diagnosis of retrieval failures, see Ralph code search problems. For the structural model behind task-sized context, see knowledge graphs for AI coding assistants.

Leave a Reply