Skip to content

Scope agent context: extract conventions, enforce git restrictions via hooks#258

Draft
KRRT7 wants to merge 5 commits intomicrosoft:mainfrom
KRRT7:scoped-agent-context
Draft

Scope agent context: extract conventions, enforce git restrictions via hooks#258
KRRT7 wants to merge 5 commits intomicrosoft:mainfrom
KRRT7:scoped-agent-context

Conversation

@KRRT7
Copy link
Copy Markdown
Contributor

@KRRT7 KRRT7 commented Apr 29, 2026

Summary

  • Extracts code generation conventions from AGENTS.md into .github/code-conventions.md — only loads when writing/generating code, not every interaction
  • Replaces text-based "NEVER COMMIT CODE" with a PreToolUse hook (scripts/block-git-mutations.sh) that actually blocks git mutations
  • Registers the hook for both Claude Code (.claude/settings.json) and VS Code Copilot (.vscode/settings.json)
  • AGENTS.md goes from 106 → 32 lines — only core workflow rules remain

Related discussion: #257

How it works

The hook script receives tool invocations as JSON on stdin, checks if it's a terminal command containing a git mutation (commit, add, push, reset, rebase, merge, cherry-pick, revert, stash, tag), and returns a deny decision. Read-only commands (status, diff, log, show, branch) pass through.

Verifying hooks

Tests: 39 pytest tests cover blocking mutations, allowing read-only commands, allowing non-git commands, and ignoring non-terminal tools:

uv run pytest tests/test_hooks.py -v

Live verification:

  • Claude Code: run /hooks to confirm the PreToolUse hook is registered
  • VS Code Copilot: check agent logs for hook execution

Docs

Test plan

  • uv run pytest tests/test_hooks.py -v — 39/39 passing
  • Live test: trigger git commit in Claude Code session, verify it's blocked
  • Live test: trigger git commit in VS Code Copilot session, verify it's blocked

Copy link
Copy Markdown
Collaborator

@gvanrossum gvanrossum left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not bad for a first draft, but I have some issues about what goes where.

Comment thread .vscode/settings.json
@@ -0,0 +1,11 @@
{
"github.copilot.chat.agent.hooks": {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This file varies per user. We can't replace it with this. At best we could move this to README.md for humans to manually add there. (Or possibly we can add it to AGENTS.md. :-)

Comment thread .gitignore
@@ -1,5 +1,6 @@
# Editor settings
.vscode
# Editor settings (but .vscode/settings.json is tracked for Copilot hooks)
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So I would be against this.

Comment thread .claude/settings.json
@@ -0,0 +1,11 @@
{
"hooks": {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same objection as for .vscode

@@ -0,0 +1,62 @@
When generating Python code (e.g. when translating TypeScript to Python),
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't like hiding things under .github either. If we want to go through with this (I'm still skeptical) we should collect all the agent instructions in a single top-level directory (not hidden) and explain in AGENTS.md how to use them.

@@ -1 +1,3 @@
Get your instructions from AGENTS.md in the repo root.

For code generation and style conventions, see [code-conventions.md](code-conventions.md).
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Move this into AGENTS.md

Comment thread scripts/block-git-mutations.sh Outdated
Comment thread scripts/block-git-mutations.sh Outdated
Comment thread scripts/block-git-mutations.sh Outdated
Comment thread AGENTS.md
Comment on lines -5 to -9
Never run git commands that make any changes. (`git status` and `git diff` are fine)

**NEVER COMMIT CODE. Do not run `git commit` or any other git commands
that make changes to the repository. Not even `git add`**

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would keep this and use the hook script as a second defense.

Comment thread AGENTS.md Outdated
Comment on lines -12 to -15
When I ask to update AGENTS.md (even if maybe) extract a general rule from what I said
before and update AGENTS.md (unless it's already in there -- maybe reformulate since
it apparently didn't work). Also, when it looks like I state a general rule, add it to
AGENTS.md. In all cases show what you added to AGENTS.md.
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why delete this? I want it to learn from its mistakes. (Though it may have to point at a different file or files.)

@KRRT7
Copy link
Copy Markdown
Contributor Author

KRRT7 commented May 1, 2026

Pushed updates addressing your feedback. Here's what changed and where I disagree:

Tracked settings files (.vscode/settings.json, .claude/settings.json)

These aren't user-specific editor preferences — they're project-level hook registrations. Both tools explicitly distinguish shared vs personal config:

  • VS Code: "Workspace settings are specific to a project and can be shared across developers on a project... This makes it easy to share settings with others in a version-controlled (for example, Git) project." (docs)
  • Claude Code: .claude/settings.json is "checked into source control and shared with your team"; .claude/settings.local.json is "not checked in, useful for personal preferences" (docs)

The .gitignore uses !.vscode/settings.json to track only that file — everything else under .vscode/ stays ignored.

.github/ location

.github/copilot-instructions.md is GitHub's standard path — Copilot auto-loads it. Moving it elsewhere means Copilot won't find it. Similarly, .github/code-conventions.md is linked from both AGENTS.md and copilot-instructions.md so each tool follows its own standard discovery path.

The point of splitting is lazy loading. Three tools' own docs recommend this:

  • Claude Code: "Target under 200 lines per CLAUDE.md file. Longer files consume more context and reduce adherence." (docs)
  • GitHub Copilot: supports .github/instructions/NAME.instructions.md scoped to matching file paths (docs)
  • Cursor: "Keep rules under 500 lines" and "Split large rules into multiple, composable rules." (docs)

Hook rewritten in Python (fixes Windows, bypass, git branch)

Rewrote block-git-mutations.shblock_git_mutations.py. Addresses all three concerns:

  • Cross-platform via uv run python. VS Code hooks natively support per-OS commands (windows/linux/osx keys) (docs)
  • Allowlist approach — only known-safe subcommands pass, everything else denied by default
  • shlex.split() for proper shell parsing, resolves git aliases via git config --get-regexp, handles &&/||/;/| chains
  • git branch -d/-D/-m, git tag -a/-d/-f, git stash (without list/show), git worktree (without list) all correctly blocked

92 tests, pure Python, no subprocess dependency.

AGENTS.md — trimmed, not restored

You said "use the hook script as a second defense" — I took that further. The hook is the first line of defense: deterministic, zero context cost, can't be talked out of it. That means AGENTS.md doesn't need to repeat the git rules in prose. It went from 106 → 35 lines. Everything that can be enforced by a hook should be, so the agent context budget is spent on things that actually need natural language (workflow, conventions, preferences).

KRRT7 added 4 commits May 1, 2026 03:03
…git restrictions

- Extract code generation conventions from AGENTS.md into .github/code-conventions.md
- Replace text-based "NEVER COMMIT" instruction with a PreToolUse hook that blocks git mutations
- Register hook for Claude Code (.claude/settings.json) and VS Code Copilot (see PR notes)
- Add 39 pytest tests verifying the hook blocks mutations and allows read-only commands
- AGENTS.md reduced from 106 to 32 lines — only core workflow rules remain
Makes git-mutation enforcement work out-of-the-box for VS Code Copilot
users instead of requiring manual setup.
- Replace bash hook with cross-platform Python script using allowlist
  approach, shlex parsing, git alias resolution, and chained command
  handling
- Restore removed AGENTS.md sections (worktrees, debugging, self-learning)
- Hook is first line of defense; AGENTS.md just references it
- Update .claude/settings.json and .vscode/settings.json with Python
  invocation and Windows-specific command
- Rewrite tests as pure Python unit tests (92 cases, no subprocess)
Remove restored worktrees, debugging, and self-learning sections.
The hook handles git enforcement deterministically; AGENTS.md stays
lean to minimize context consumption.
@KRRT7 KRRT7 force-pushed the scoped-agent-context branch from 043c3f8 to 87b3261 Compare May 1, 2026 08:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants