pi-repo-state
Lightweight on-demand git repository snapshot for pi agents: one call returns branch/ahead-behind/dirty counts/diff stats/conflicts/recent commits, directly spawning git (no shell wrapping, no per-prompt injection, no TUI — avoids the stale-context crash
Package details
Install pi-repo-state from npm and Pi will load the resources declared by the package manifest.
$ pi install npm:pi-repo-state- Package
pi-repo-state- Version
0.1.0- Published
- Aug 9, 2026
- Downloads
- 169/mo · 14/wk
- Author
- nuctori
- License
- MIT
- Types
- extension
- Size
- 41.8 KB
- Dependencies
- 0 dependencies · 2 peers
Pi manifest JSON
{
"extensions": [
"./extensions"
]
}Security note
Pi packages can execute code and influence agent behavior. Review the source before installing third-party packages.
README
pi-repo-state
Lightweight, on-demand git repository snapshot for pi agents — without the costs of the community alternative.
Why this exists
We audited pi-git-context (the community git-state package) over a 122-session window and found three problems:
- Crash: it uses a module-captured
ctxinupdateFooter— on session replacement/reload thectx.uigetter throwsstale ExtensionContext, which killed 3/3 parallel subagents in our run (reported upstream: h14h/pi-packages#3). - 46% shell polling: per-prompt snapshot injection turned 46% of all
ctx_shellcalls into git polling (a singlegit logcommand repeated 1,285× in one window). - Cache-prefix breakage: every snapshot change invalidates the prompt-cache prefix, forcing re-processing of the changed tail on each prompt.
pi-repo-state is the opposite design: on-demand, no injection, no TUI, no captured ctx.
Install
pi install npm:pi-repo-state # once published
pi install /path/to/packages/pi-repo-state # local dev
Then /reload or start a new session.
Tool: repo_state
| Parameters | { force?: boolean, depth?: "quick" | "full" } — 3s cache |
| Returns | verdict-first snapshot: repo: / branch: <name> — ahead N / behind M (upstream X) / dirty: N modified, N staged, N untracked, N deleted[, N CONFLICTS] / diff: +N/-N across N files (top files) / recent: <sha> <subject> / remote: / worktrees: |
| Non-repo | clear verdict not a git repository (no guessing) |
| Implementation | directly spawns git -C <cwd> — cross-platform, no shell wrapping; all fields parallel; failures degrade per-field |
repo: D:/cs/KoishiNavigationRebuildMain
branch: main — ahead 2 / behind 0 (upstream origin/main)
dirty: 6 modified, 3 staged, 31 untracked, 1 deleted
diff: +214/-87 across 12 files
top: GameMap.xaml.cs (+120/-40), SettingWindow.xaml (+30/-5), ...
recent: abc1234 fix: hot path alloc | def5678 feat: settings window
remote: cnb.cool/.../koishiNavigationEvo
Design decisions (vs pi-git-context)
| pi-git-context | pi-repo-state | |
|---|---|---|
| Trigger | inject every prompt | on demand (model calls it) |
| Ongoing cost | 46% of shell calls were git polling | zero until called |
| Cache prefix | broken on each snapshot change | never touches the prompt |
| TUI / ctx capture | footer via captured ctx (crash) | none |
| Shell | uses shell wrapping | direct git spawn |
Test
npm install && node test/smoke-test.cjs && node test/smoke-inject.cjs
Optional: minimal turn-0 injection
extensions/git-mini-inject.ts (same package) injects a high-density project
version/iteration snapshot at turn 0 only (the first LLM call of each user
request), appended at the end of the message array:
[iter] remote github.com/example/repo | default master (05a2094) ahead0/b0 | branch feature (b5ca078) +2 from master | dirty 0m/0s/0u/0d
Covers: remote · default branch (sha + ahead/behind vs origin) · current branch
(+N commits from default = iteration distance) · version (package.json / git
describe) · dirty counts · worktree topology (linked? primary? total). Degrades
gracefully without a remote (branch/ver/dirty only). Turns > 0 strip it; use
repo_state for fresh detail mid-turn. Opt out with PI_REPO_STATE_INJECT=off.
Cache trade-off (measured): across requests the injection adds only a ~100-token
tail suffix (prefix cache preserved); within a request, the turn0→turn1 boundary
re-processes the first assistant response once per tool-loop request (bounded,
vs pi-git-context which broke the prefix on every snapshot change). If git status times out (>3s) the line shows dirty ?/?/?/? rather than claiming
clean.
License
MIT