Connect sessions to Git commits
Install Sher's Git and agent hooks to find the conversation behind a commit.
Sher can record commits and connect them to the conversation that produced a surviving file change. This runs entirely on your machine: no login, no upload, no server involved. GitHub PR tracking and comments are a later stage.
What it does
After you install Sher's Git hooks and an agent bridge, Sher watches commits made in a repository
and matches them against tool edits it saw in your agent sessions. A match becomes a link
between a session and a commit only when the evidence is strong enough — see
What a link means. Everything indexed this way stays local; sher context
reads it back without a network round trip.
Install
Run these from inside a Git working tree, using the Sher build you want linking to observe:
sher hooks install
sher hooks agents install claude
# Or: sher hooks agents install codex
# Or: sher hooks agents install ompRestart the agent so it loads its bridge. Agent installation uses the agent's active configuration
directory; --config-dir PATH selects an explicit one. Installing a hook does not bypass the
agent's own hook trust or policy checks.
Git hooks apply to the repository, including any linked worktrees. Install the agent bridge once
per configuration or profile you use — a second machine or a second agent account needs its own
hooks agents install.
Keep the Sher daemon running so it can discover new transcripts and process receipts:
sher daemon install
sher daemon startFor a one-off local trial without the daemon, run sher daemon --once.
Commits without a hook receipt
Git runs Sher's hook for every ordinary git commit once the hooks are installed. The daemon also
covers the commits the hook never saw:
- commits made before you ran
sher hooks install - commits made while another tool had replaced Sher's
core.hooksPathsetting
On each audit pass the daemon walks the local branches and the checked-out HEAD of every worktree
in repositories it knows about. It does not walk remote-tracking branches or tags. It attributes a
commit only when its branch is checked out in a worktree; a commit on a branch that no worktree has
checked out is recorded as seen but never matched.
A commit found this way is held to the same proof as a hook receipt. It can link as a contribution, but never as an invocation, because nothing records which session ran Git.
Find the conversation
Once you or the agent has committed a captured change:
sher hooks status
sher context query --commit FULL_COMMIT_HASH
sher context get CONTEXT_IDsher context query --commit returns accepted links only. Widen it with --decision any (or a
specific decision such as --decision candidate) to see relationships Sher considered but did not
accept automatically, or that you or the agent later rejected. Add --json for machine-readable
output.
What a link means
- Contributed — a successful, identified tool edit has a uniquely verifiable change still present in the commit. A human can commit it after the agent exits.
- Invoked — evidence identifies the session and tool call that ran Git. It does not mean that session wrote everything in the commit. Only a commit seen by Sher's Git hook can have an invoker.
- Candidate — evidence is incomplete, or competing edits prevent confident attribution. A
candidate is inspectable with
--decision candidate, never returned as a link by default. Sher does not turn timing or a shared branch into authorship.
When links do not appear
Sher's matcher is deliberately strict, because a wrong link is worse than a missing one:
- Overlapping or ambiguous edits. If more than one tool call plausibly produced the same surviving change, both stay candidates.
- Shell edits that are not proven. A shell command (for example
sed -ithrough Bash) can produce a contribution only when all of these hold: the command text names the file, Sher's before/after snapshot shows a change that survives in the commit, no other recorded writer touched that file, and the transcript shows the call succeeded. Snapshots are bounded: a call that changes more than eight files, or whose snapshot fails or times out, gets no link. Today only Codex records whether a shell call succeeded, so shell-edit links appear for Codex. A shell edit made through Claude Code or OMP stays pending and is not linked. - A shell call that ended before the commit. It can be a contributor, but it is never the invoker, even in the session that later ran Git. A single call that both edits and commits can be both.
- Rewrites. After an amend, rebase, or squash, Sher records which new commit replaced which old
one, as Git reports it. Each new commit is checked again against its own parent, with the same
proof as any other commit. A link is never copied from an old commit to a new one, and the old
commit keeps its link. An amend or a clean rebase usually links again. A squash that merges two
edits of the same lines does not.
sher context query --commitshowsrewritten_toon an old commit andrewritten_fromon a new one. A rewrite Sher did not see, such as a force-push from another machine, is not linked again. - Large or binary files, and unsupported tool paths. These never receive an automatic contribution claim.
An automatically accepted link can still be weakened by later competing evidence. An explicit correction you make — accepting, rejecting, or reviewing a relationship — is preserved.
Status and removal
sher hooks status
sher hooks agents status claudesher hooks status prints a plain-language report by default; add --json for a stable,
machine-readable form that includes a state field. The state is one of:
not_installed— Sher's hooks are not set up here. The message names the install command.installed— Git runs Sher's hooks for this repository.displaced— Sher's hooks are installed, but another tool (for example husky) now setscore.hooksPath. The message names that value and how to fix it:sher hooks install --reinstallchains Sher back in ahead of it, orsher hooks remove --forceremoves only Sher's own files and leaves the other tool in place. The daemon still observes commits reachable from local branches even while displaced.edited— a hook file no longer matches what Sher wrote. Sher will not overwrite it silently.executable_missing— the Sher executable pinned at install time can no longer be found. Restore it, or reinstall from the executable you want to use.
It also reports how many receipts are pending, parked as invalid, or only partly written, whether any capture was lost, and what the local ledger has stored. A healthy status does not by itself promise complete capture: the daemon may need another pass when a transcript write lags its callback.
Sher owns a private hook directory and forwards to any existing hook, preserving its arguments,
input, and exit status. It refuses to silently touch a hook it did not install or that was edited
by something else. sher hooks remove restores the prior core.hooksPath; pass --force to
remove only Sher's own hook files when another tool has since taken over core.hooksPath.
sher hooks agents remove claude
sher hooks removeChoose the provider you installed. Removal preserves unrelated agent configuration and restores
the Git hook setting that was in place before Sher installed its own. Historical receipts and
relationships already recorded remain available through sher context.
Going back to Sher 0.1
Sher 0.1 has no hooks command, so it is still best to remove the hooks and agent bridges before
you install it: run sher hooks agents remove <claude|codex|omp> for each agent you connected, and
sher hooks remove in each connected repository. Your sessions and Sher's local data are not
affected, and Sher 0.1 opens them as before.
Removal first is recommended, not required: the Claude Code and Codex bridges fail open, so if you
go back without removing them, Sher just stops capturing and your tool calls keep working. Git
still skips your own post-commit and post-rewrite hooks in connected repositories, though,
because Sher's Git hook wrapper calls Sher before forwarding to yours, and Sher 0.1 does not
understand the wrapper's request. Fix that (or an already-installed bridge you would rather remove
by hand) like this:
- Claude Code or Codex: in
~/.claude/settings.jsonor~/.codex/hooks.json, delete every hook whose command ends inhooks agent claudeorhooks agent codex. - OMP: delete
~/.omp/agent/extensions/sher.ts. - Each repository: run
git config --unset core.hooksPath, or set it back to the value you had before installing Sher, then delete thesher-hooksdirectory inside.git.
Supported platforms and providers
Git-linking is qualified on Linux. Runtime checks used Claude Code, Codex, and OMP; all three produced accepted edit contributions, and Claude and Codex also produced separate invocation links. OMP invocation is currently unqualified. Shell-edit links are qualified for Codex only. A Codex shell-intercepted patch can omit a completion callback and fall back to transcript metadata instead of a shell-edit link.
macOS support for Git-linking is pending a maintainer check on a Mac; until then, treat it as Linux-only.
See docs/git-capture.md in the
repository for the maintainer-facing reference, including exact provider versions and observed
payloads.