Describe the bug
Summary
Custom instruction discovery canonicalizes the path of any file a tool touches, then loads AGENTS.md from every ancestor directory of the resolved path. Git repository boundaries are not honored.
For anyone whose dotfiles are a git repo with ~/.copilot (or ~/.claude, ~/.config/...) symlinked into it — a very common setup — this means the dotfiles repo's own AGENTS.md is silently injected into every unrelated session, on every machine, as soon as the agent reads any file under the symlinked config directory.
The docs describe the behavior as AGENTS.md "in the git root and cwd". The actual behavior is much broader.
Reproduction
~/dotfiles/ <- a git repo
AGENTS.md <- rules meant only for working on the dotfiles repo
config/copilot/
settings.json
~/.copilot -> ~/dotfiles/config/copilot (symlink)
~/work/my-app/ <- an unrelated project, different git repo
cd ~/work/my-app
- Start the CLI and ask it anything that causes it to read a file under
~/.copilot — for example, read ~/.copilot/settings.json.
~/dotfiles/AGENTS.md is now in context.
Observed with --log-level debug; the log shows the dotfiles repo's AGENTS.md being registered as a custom instruction source.
Expected
~/dotfiles/AGENTS.md should not load. The session's git root is ~/work/my-app, cwd is ~/work/my-app, and the user never asked for the dotfiles repo's conventions. Reading a config file is not a statement of intent to adopt another repository's instructions.
Actual
The path is canonicalized to ~/dotfiles/config/copilot/settings.json, and discovery then walks up through config/copilot → config → dotfiles → ~, collecting AGENTS.md at each level.
Why this is more than cosmetic
- It is silent. There is no indication in normal (non-debug) output that a foreign repository's instructions were loaded. Users experience it as unexplained behavior drift.
- It is contagious. The dotfiles repo is exactly where people put rules like "always commit and push when done" or "never run destructive cleanup here". Those rules are correct for that repo and actively wrong everywhere else.
- It is triggered by the agent's own housekeeping. The user does not have to do anything unusual; any tool call that touches the config directory is enough.
- It affects the fix, too. Users who notice and try to scope things out cannot.
Workarounds tested — all fail
| Attempt |
Result |
Put the config dir in a git worktree of the same repo |
Still leaks. Git root correctly resolves to the worktree, but discovery walks to the main repo root anyway. |
Make the config dir its own independent git repo (own .git) |
Still leaks. The ancestor walk goes straight past the nested git boundary. |
Shadow with a nearer AGENTS.md |
Does not shadow. All ancestor-level AGENTS.md files load simultaneously. |
| Use a junction instead of a symlink (Windows) |
No difference; both are reparse points and both are collapsed by path canonicalization. |
Disable the source via /instructions |
Not persistent. The toggle lives in per-session state and resets on the next session, unlike skill toggles which are written to settings. |
| Set a config key |
None exists. On-demand instruction discovery appears to be enabled unconditionally. |
The only workaround that works is renaming the dotfiles repo's AGENTS.md to something outside the auto-load list, which means giving up per-repo agent instructions for that repo entirely.
Suggested fixes (any one would resolve it)
- Do not canonicalize for discovery purposes. Walk ancestors of the logical path the user/tool referenced, not the resolved real path. This alone fixes the whole class of dotfiles cases.
- Stop the ancestor walk at a git boundary, and do not cross out of the session's own repository into a different one.
- Do not run ancestor discovery for incidental file reads at all — restrict it to the session's git root and cwd, matching the documented behavior.
- At minimum, make it persistent-configurable: a
settings.json key (disabledInstructionSources, or an allowlist of instruction roots) so the /instructions toggle survives across sessions.
Fix 1 or 2 would be the principled fix. Fix 4 would at least give users an escape hatch.
Related
~/.copilot/instructions/ only matches **/*.instructions.md. A file named AGENTS.md placed there is ignored silently, with no warning — which is easy to trip over given that AGENTS.md is the recognized name nearly everywhere else. A startup warning for non-matching files in that directory would save people a lot of time.
Affected version
GitHub Copilot CLI 1.0.83, but seems like any version is affected
Steps to reproduce the behavior
- Make a git repo at
~/dotfiles containing an AGENTS.md at its root (rules meant only for that repo) and a config/copilot/ directory inside it.
- Symlink
~/.copilot -> ~/dotfiles/config/copilot.
cd into an unrelated project in a different git repo, e.g. ~/work/my-app.
- Start the CLI there and ask it to read any file under the config dir, e.g.
read ~/.copilot/settings.json.
- Re-run with
--log-level debug and grep the log for custom instruction sources.
~/dotfiles/AGENTS.md is registered as a source and is in context, even though it belongs to a different repository.
Expected behavior
~/dotfiles/AGENTS.md should not load. Both the git root and cwd are ~/work/my-app, and the docs describe discovery as AGENTS.md in the git root and cwd. Reading a config file that happens to live inside another git repo should not import that repo's instructions. Discovery should walk the logical path rather than the symlink-resolved real path, and should not cross out of the session's own repository.
Additional context
No response
Describe the bug
Summary
Custom instruction discovery canonicalizes the path of any file a tool touches, then loads
AGENTS.mdfrom every ancestor directory of the resolved path. Git repository boundaries are not honored.For anyone whose dotfiles are a git repo with
~/.copilot(or~/.claude,~/.config/...) symlinked into it — a very common setup — this means the dotfiles repo's ownAGENTS.mdis silently injected into every unrelated session, on every machine, as soon as the agent reads any file under the symlinked config directory.The docs describe the behavior as
AGENTS.md"in the git root and cwd". The actual behavior is much broader.Reproduction
cd ~/work/my-app~/.copilot— for example,read ~/.copilot/settings.json.~/dotfiles/AGENTS.mdis now in context.Observed with
--log-level debug; the log shows the dotfiles repo'sAGENTS.mdbeing registered as a custom instruction source.Expected
~/dotfiles/AGENTS.mdshould not load. The session's git root is~/work/my-app, cwd is~/work/my-app, and the user never asked for the dotfiles repo's conventions. Reading a config file is not a statement of intent to adopt another repository's instructions.Actual
The path is canonicalized to
~/dotfiles/config/copilot/settings.json, and discovery then walks up throughconfig/copilot→config→dotfiles→~, collectingAGENTS.mdat each level.Why this is more than cosmetic
Workarounds tested — all fail
git worktreeof the same repo.git)AGENTS.mdAGENTS.mdfiles load simultaneously./instructionsThe only workaround that works is renaming the dotfiles repo's
AGENTS.mdto something outside the auto-load list, which means giving up per-repo agent instructions for that repo entirely.Suggested fixes (any one would resolve it)
settings.jsonkey (disabledInstructionSources, or an allowlist of instruction roots) so the/instructionstoggle survives across sessions.Fix 1 or 2 would be the principled fix. Fix 4 would at least give users an escape hatch.
Related
~/.copilot/instructions/only matches**/*.instructions.md. A file namedAGENTS.mdplaced there is ignored silently, with no warning — which is easy to trip over given thatAGENTS.mdis the recognized name nearly everywhere else. A startup warning for non-matching files in that directory would save people a lot of time.Affected version
GitHub Copilot CLI 1.0.83, but seems like any version is affected
Steps to reproduce the behavior
~/dotfilescontaining anAGENTS.mdat its root (rules meant only for that repo) and aconfig/copilot/directory inside it.~/.copilot->~/dotfiles/config/copilot.cdinto an unrelated project in a different git repo, e.g.~/work/my-app.read ~/.copilot/settings.json.--log-level debugand grep the log for custom instruction sources.~/dotfiles/AGENTS.mdis registered as a source and is in context, even though it belongs to a different repository.Expected behavior
~/dotfiles/AGENTS.mdshould not load. Both the git root and cwd are~/work/my-app, and the docs describe discovery asAGENTS.mdin the git root and cwd. Reading a config file that happens to live inside another git repo should not import that repo's instructions. Discovery should walk the logical path rather than the symlink-resolved real path, and should not cross out of the session's own repository.Additional context
No response