Guide
Verify Git identity before an agent commits
Point Claude Code, Codex, or Cursor at the gitrole skill shipped in the npm package so the agent runs status --short before it commits and stops on a warning.
The packaged gitrole skill instructs an agent to check the repository's effective identity and stop on warnings. It supplies instructions, not an enforced Git permission boundary.
Quick start
You need gitrole on PATH (brew install synthesiseng/tap/gitrole, or npm install -g gitrole). The skill file ships in the npm package. This quick start uses a global npm install and symlinks that folder into the two example personal skill directories. A symlink keeps the skill on the package when you upgrade, instead of copying a stale file.
GITROLE_SKILL="$(npm root -g)/gitrole/skills/gitrole"
if [ -f "$GITROLE_SKILL/SKILL.md" ]; then
mkdir -p ~/.claude/skills ~/.agents/skills
for GITROLE_SKILL_LINK in ~/.claude/skills/gitrole ~/.agents/skills/gitrole; do
if [ -e "$GITROLE_SKILL_LINK" ] || [ -L "$GITROLE_SKILL_LINK" ]; then
printf 'Review existing skill path: %s\n' "$GITROLE_SKILL_LINK"
else
ln -s "$GITROLE_SKILL" "$GITROLE_SKILL_LINK"
fi
done
else
printf '%s\n' 'Skill file not found; check the package or checkout path.'
fi
Confirm that your agent has loaded the skill using that tool's current skill setup instructions. These paths are examples of common skill locations; loading and automatic invocation depend on your agent and version.
Homebrew users can set GITROLE_SKILL to /absolute/path/to/gitrole/skills/gitrole in a source checkout instead. The npm example requires the npm package to be installed. No supported Homebrew asset path is documented here.
How the agent reads the check
Use gitrole status --short as the precommit gate, including before the first commit:
gitrole status --short
The line is role scope override commit remote auth policy overall. The agent reads the fields by name. overall is the eighth field, after policy, because a parser that still treats field seven as the summary is reading policy.
| Result | Action |
|---|---|
Exit 0 and overall=aligned | Identity checks are aligned. Proceed only within existing user authorization; this does not prove push permission or success. |
Exit 2 or overall=warning | Stop. Do not commit or push. |
commit, remote, auth, or policy is warn | Stop. Do not commit or push. |
Exit 1 | Stop. The error is on stderr and stdout is empty. Do not commit or push. |
na means that check doesn't apply. It doesn't by itself mean stop. policy=na with overall=aligned is aligned, because there is no .gitrole file to violate.
An aligned local role with no .gitrole file looks like this:
role=work scope=local override=true commit=ok remote=ok auth=ok policy=na overall=aligned
Trust the effective identity
GIT_AUTHOR_NAME, GIT_AUTHOR_EMAIL, GIT_COMMITTER_NAME, and GIT_COMMITTER_EMAIL override Git config. Agents set those variables often. A present user.name or user.email doesn't mean the commit is aligned, so the agent has to read gitrole instead of the config keys.
On gitrole doctor --json, commitIdentity is the effective name and email. Each source is local, global, system, worktree, command, git, env, or unset. configuredIdentity is only the raw config, so an env override can leave configuredIdentity looking fine while commitIdentity is someone else.
An env value that moves the author off the saved role is commit=warn and overall=warning. This line is GIT_AUTHOR_EMAIL set to an address that matches no saved role, on a global identity that otherwise matches work:
role=no-role scope=global override=false commit=warn remote=ok auth=ok policy=na overall=warning
GIT_COMMITTER_EMAIL or GIT_COMMITTER_NAME that disagrees with the effective author is also commit=warn and exit 2. The role can still match, because the author didn't change:
role=work scope=global override=false commit=warn remote=ok auth=ok policy=na overall=warning
An env value that matches the saved role can be info with overall=aligned. That info is not a warning. The agent still uses the gitrole result, not the config keys.
Warnings that still stop
These are overall=warning and exit 2. The agent stops and doesn't commit.
HTTPS-only push destination with no .gitrole pin. auth=warn because the local HTTPS check requires an allowing pin and a saved githubUser. Even then the pin does not verify or select HTTPS credentials. auth=na on HTTPS is only that pinned case. Anything else warns, including a clean commit identity:
role=work scope=local override=true commit=ok remote=ok auth=warn policy=na overall=warning
A repository with no commits and no local role. commit=warn protects against taking the global identity for the first commit. The push destination is checked separately; an unborn branch can still resolve a destination:
role=work scope=global override=false commit=warn remote=ok auth=ok policy=na overall=warning
An explicit local role can keep commit=ok. If the destination, supported authentication and policy also pass, status can be aligned even before the first commit. That observes identity; it does not prove branch/refspec readiness or that a push succeeds.
Full diagnosis
Use doctor for broader diagnosis when a check needs explanation. Doctor is not a substitute for the precommit gate:
gitrole doctor --json
Doctor also checks history. A fresh repository with an explicit local role and an allowing HTTPS pin can have aligned status while doctor exits 2 with only a history warning because it has no commits. Run the status gate before the separately authorized first commit; do not create a commit just to silence doctor. If doctor was run first, use status for the precommit decision. Other diagnostic warnings or errors require investigation; a clean status does not dismiss them.
Do not bypass any status warning. Status exit 1 or 2 still stops the agent. Doctor warnings remain warnings; do not filter checks to turn the diagnosis into a pass. info is not a warning. Doctor exit 1 prints no JSON. Don't parse checks[].message. Field names are in Machine Readable Contracts.
What it doesn't do
The skill doesn't install a git hook, switch roles, or block git. It checks, and the agent decides to stop. Scripted preflight without a skill is in Use gitrole as an identity preflight for agents and automation.
The optional hooks/pre-commit asset now runs gitrole check commit, a local identity and policy guard. It requires a full saved-role match even without a pin. It does not change this skill's strict status --short gate. Existing copied hooks that run status keep their earlier behavior until manually migrated. For installation, compatibility, backup and rollback guidance, read Check identity before a local commit.
Where the skill lives
| Install | Skill directory |
|---|---|
| Global npm install | $(npm root -g)/gitrole/skills/gitrole |
| Project dependency | node_modules/gitrole/skills/gitrole |
| Checkout of this repository | skills/gitrole |
For a project dependency, run this from the project root. The skill must exist in that project's node_modules before links are created:
GITROLE_SKILL="$(pwd)/node_modules/gitrole/skills/gitrole"
if [ -f "$GITROLE_SKILL/SKILL.md" ]; then
mkdir -p .claude/skills .agents/skills
for GITROLE_SKILL_LINK in .claude/skills/gitrole .agents/skills/gitrole; do
if [ -e "$GITROLE_SKILL_LINK" ] || [ -L "$GITROLE_SKILL_LINK" ]; then
printf 'Review existing skill path: %s\n' "$GITROLE_SKILL_LINK"
else
ln -s "$GITROLE_SKILL" "$GITROLE_SKILL_LINK"
fi
done
else
printf '%s\n' 'Skill file not found; check the project installation path.'
fi
For a global npm package, set GITROLE_SKILL to $(npm root -g)/gitrole/skills/gitrole instead. For checkout assets, use the absolute checkout path. Existing links are left in place; review them before changing their targets.
Configure your agent to load this skill according to its current documentation, then confirm it runs the check. The links above place the skill in common project directories; they do not prove that every agent or version has loaded it. Review any existing links before replacing them.