Agents should read between the lines.
git-span documents implicit dependencies, the invisible connections in your project that type systems cannot see. Coding agents using git-span understand how the changes they make will affect other parts of your project.
Some files depend on each other without being directly connected.
Separate parts of a repository often participate in the same behavior. An API response and the client code that reads it. SDKs written in different languages. No import, type, or reference connects these sections, but changing one can require attention elsewhere. Without a place to record the connection, it survives only as long as someone remembers it.
$ cat ./api/src/routes/products.ts | sed -n '4,7p'
return {
items: items.slice(0, limit),
page: page.nextPage
};
$ cat ./client-py/pagination.py | sed -n '25,27p'
def fetch_page(params):
response = get_products(params)
next_page = response["page"]Coding agents make changes without understanding the consequences.
Your coding agent renames an API response field, implemented in TypeScript, from “page” to “cursor.” Git records the edited line exactly. Nothing in the commit points to the Python client that still reads “page.”
$ git show ./api/src/routes/products.ts
@@ -3,6 +3,6 @@ function listProducts(q: ProductQuery) {
return {
items: items.slice(0, limit),
- page: page.nextPage,
+ cursor: page.nextCursor,
};By the time you notice the integration problems, it’s too late.
The API change looks complete. Then the catalog sync reaches the untouched client and crashes. The connection becomes visible only after the work looked finished, when rediscovering it costs the most.
$ python ./scripts/sync_catalog.py
page = fetch_page(cursor)
File "client-py/pagination.py", line 27, in fetch_page
next_page = response["page"]
~~~~~~~~^^^^^^^^
KeyError: 'page'Spans document these indirect connections and monitor changes.
A span gives the connection a name, identifies the files and line ranges involved, and records the nonlocal fact that changes a safe decision. It lives in .span/ as ordinary tracked text, so it can be reviewed, committed, and shared with the code. Content hashes of the range are stored to detect changes.
$ cat ./.span/product-listing-pagination
api/src/routes/products.ts#L4-L7 rk64:38db8e8540025b2a
client-py/pagination.py#L25-L27 rk64:f4df18e9b3e72d2a
The API pagination response is authoritative;
clients consume its continuation cursor unchanged.git-span notifies coding agents when they read or write connected files.
When a coding agent reads or edits a recorded line range, git-span puts the span into its context before the tool runs. The agent receives the span’s name, every connected location, and the explanation of how those sections relate. The client that was absent from the diff is now part of the work.
● Update(api/src/routes/products.ts)
⎿ Added 1 line, removed 1 line
4 return {
5 items: items.slice(0, limit),
6 - page: page.nextPage,
6 + cursor: page.nextCursor
7 };
⎿ PostToolUse says: <git-span>
## product-listing-pagination
api/src/routes/products.ts#L4-L7
client-py/pagination.py#L25-L27
The API pagination response is authoritative;
clients consume its continuation cursor unchanged.
</git-span>Connected files are now updated together, so integration never breaks.
The agent follows the surfaced location, reads the client code, and updates it to use “cursor.” git-span never edits source code or chooses the fix. It brings recorded knowledge into the work while there is still time to act on it.
$ git show ./client-py/pagination.py
@@ -24,5 +24,5 @@ def get_products(params):
def fetch_page(params):
response = get_products(params)
- next_page = response["page"]
- return next_page
+ next_cursor = response["cursor"]
+ return next_cursorAgents using git-span complete tasks faster, with fewer mistakes.
The API and client now agree on “cursor.” The catalog sync passes. No late crash. No return to work everyone thought was finished. Git tracked the edits. The span kept the connection visible.
$ cat ./api/src/routes/products.ts | sed -n '4,7p'
return {
items: items.slice(0, limit),
cursor: page.nextCursor
};
$ cat ./client-py/pagination.py | sed -n '25,27p'
def fetch_page(params):
response = get_products(params)
next_cursor = response["cursor"]