github / github/copilot-cli

COPILOT_CUSTOM_INSTRUCTIONS_DIRS only half-honored by instruction loader (1.0.54)

Open
#3,507 0 comments 2 reactions 0 assignees View on GitHub
area:configuration area:context-memory
Dominant language
Shell
Stars
11.2k
Forks
1.9k
Avg merge
14h 16m
Merged PRs (30d)
6

Description

# Bug: `COPILOT_CUSTOM_INSTRUCTIONS_DIRS` only honored for AGENTS.md + `.github/instructions/**`, not for `.github/copilot-instructions.md` / `CLAUDE.md` / `GEMINI.md`

**CLI version:** 1.0.54 (Windows, win32-x64)
**Platform:** Windows 11 / PowerShell
**Sentiment:** frown

## Summary

`COPILOT_CUSTOM_INSTRUCTIONS_DIRS` is documented in `/help` and in
`copilot --help` as a way to add **additional directories** to the
search list for custom instruction files:

> `COPILOT_CUSTOM_INSTRUCTIONS_DIRS`: comma-separated list of additional
> directories to search for custom instructions files (in addition to git
> root and current working directory).

In practice the env var is only honored for **two** of the discoverable
filenames. The other documented filenames in those same directories are
silently skipped, so users who point the env var at a sibling repo with
their canonical `.github/copilot-instructions.md` (or a `CLAUDE.md`) get
none of that content loaded.

## Repro

1. Have a directory (not cwd, not git root) containing the standard
instruction files, e.g.:

```
D:\UserRepos\zahen\
AGENTS.md (stub: "see canonical file")
CLAUDE.md (stub)
.github\copilot-instructions.md (canonical, real content)
.copilot\copilot-instructions.md (stub)
.ai\index.md
```

2. From a different cwd / different git repo, launch the CLI with:

```powershell
$env:COPILOT_CUSTOM_INSTRUCTIONS_DIRS = "D:\UserRepos\zahen"
copilot
```

3. Observe in `/env` (or in the agent system prompt) which instruction
files were discovered.

## Expected

All of these files in `D:\UserRepos\zahen\` should be loaded
(equivalent to having those dirs treated as additional git root /
cwd locations):

- `AGENTS.md`
- `CLAUDE.md`
- `GEMINI.md`
- `.github/copilot-instructions.md`
- `.github/instructions/**/*.instructions.md`

## Actual

Only `AGENTS.md` and `.github/instructions/**/*.instructions.md` are
loaded from the env-var dir. `CLAUDE.md`, `GEMINI.md`, and
`.github/copilot-instructions.md` from the same directory are **not**
loaded, even though they exist and are well-formed.

This is especially painful because in many setups (including the
official-looking convention shown in `/help`),
`.github/copilot-instructions.md` is the **canonical** file and the
sibling `AGENTS.md` / `CLAUDE.md` are pointer stubs. Loading only the
stubs leaves the agent with effectively no instructions.

## Root cause (reading `app.js` from 1.0.54)

In `async function B0i(t, e, r, n, o)` (the central instruction loader):

```js
let s = process.env.COPILOT_CUSTOM_INSTRUCTIONS_DIRS?.split(",")... ?? [];
let a = (o?.additionalDirs ?? [])...;
let l = [...new Set([...s, ...a])]; // merged extra dirs
```

`l` is then passed to exactly two collectors:

- `V0i(t, r, l)` -- scans `.github/instructions/**/*.instructions.md`
inside each dir in `l`. [ok]
- `X0i(t, l)` -- scans nested `AGENTS.md` inside each dir in `l`. [ok]

But all of the following are computed only from `t` (cwd) and `r` (git
root); `l` is never threaded through:

- `m = MYr(t)`, `_ = MYr(r)` -- `.github/copilot-instructions.md`
- `h = RYr(t)`, `S = RYr(r)` -- `AGENTS.md` (top-of-dir)
- `g = PYr(t)`, `C = PYr(r)` -- `CLAUDE.md`
- `A = NYr(t)`, `I = NYr(r)` -- `GEMINI.md`
- `f = H0i(n)` -- `$HOME/.copilot/copilot-instructions.md`

So the env-var dirs are effectively second-class: they participate in
two filename searches but not in the main `MYr/PYr/NYr/RYr` searches
that pick up the most commonly used instruction filenames.

## Suggested fix

Treat each entry in `COPILOT_CUSTOM_INSTRUCTIONS_DIRS` as an additional
"root" alongside `t` and `r` for **all** filename searches (i.e., run
`MYr/RYr/PYr/NYr` over each dir in `l` and merge the results into the
existing `Z` / `se` arrays). Behavior should match what users get if
they simply launch the CLI from that directory.

Alternatively (less surprising for users): document explicitly that the
env var only adds dirs to the `AGENTS.md` + `.github/instructions/**`
search, and recommend an `AGENTS.md`-only layout in those dirs. But the
current `/help` text reads as a general "additional directories" hint,
which is what set the wrong expectation here.

## Workarounds users currently need

- Duplicate the canonical content into `AGENTS.md` in the env-var dir
(defeats the "single source of truth" stub layout).
- Move/symlink the canonical content into `.github/instructions/...`
(requires renaming and reorganization of an existing repo).
- Launch the CLI with `-C ` so it's treated as cwd.

## Diagnostic info from my repro

- `COPILOT_CUSTOM_INSTRUCTIONS_DIRS = D:\UserRepos\zahen`
- Files present and well-formed in that dir:
`AGENTS.md`, `CLAUDE.md`, `.github\copilot-instructions.md`,
`.copilot\copilot-instructions.md`, `.ai\index.md`, `README.md`.
- Result: the agent system prompt enumerates
`D:\UserRepos\zahen\AGENTS.md` (loaded), but the much richer
`D:\UserRepos\zahen\.github\copilot-instructions.md` is not loaded.

Thanks!

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.