Skip to content

Parent repository customizations (#101) - #466

Open
Arne Deutsch (ArneDeutsch) wants to merge 5 commits into
microsoft:mainfrom
ArneDeutsch:parent-repository-customizations
Open

Arne Deutsch (ArneDeutsch) wants to merge 5 commits into
microsoft:mainfrom
ArneDeutsch:parent-repository-customizations

Conversation

@ArneDeutsch

Copy link
Copy Markdown

Problem

Custom instructions (.github/copilot-instructions.md, .github/instructions/*.instructions.md) and other customizations (prompt files, skills, custom agents) are discovered by the language server only inside the workspace folders it receives. Eclipse passes the project roots. In a typical multi-module repository, .github/ sits at the git repository root, while only the modules are imported as projects. Such customizations are therefore ignored, unless the repository root itself is imported as a project.

Solution

For every workspace folder that is located inside a git repository but is not its root, the folders up to and including the repository root are now passed to the language server as well. This mirrors VS Code's chat.useCustomizationsInParentRepositories. A .git file (worktrees, submodules) also marks a repository root, so the search stops at a submodule.

The extended folders are used for:

  • chat requests (conversation/create, conversation/turn): always-on and applyTo instructions, skills offered to the agent, custom agents as sub-agents
  • the slash command list (conversation/templates)
  • the custom agent picker (conversation/modes)
  • the customization file list used to auto-approve reads of these files
  • the tool status of custom agents

A new preference, Also load custom instructions from the parent git repository of a project, on the Custom Instructions page controls the behavior. It is enabled by default: unlike VS Code, where the repository root is usually the opened folder, Eclipse projects are commonly nested inside the repository. Toggling it refreshes the slash commands and the customization file list; the agent picker reloads when it is opened. While it is enabled, the project table on the same page also lists parent repository folders containing a .github/copilot-instructions.md, and Edit opens that file.

Additional fix: prompt files in the slash command popup (separate commit)

The language server returns prompt files with the file URI as id and a separate name, and it resolves /command by that name. The popup showed and inserted the URI (e.g. /file:///c%3A/.../review.prompt.md -), so selecting a prompt file did not apply it. This also affected prompt files inside projects. The popup now uses the name, and the - separator is omitted for templates without a description.

How to test

Create a git repository with the customizations at its root, and import only the nested project into the workspace:

repro/                                        <- git root, not imported
├── .git/
├── .github/
│   ├── copilot-instructions.md               "Always end every response with [SRC-ROOT]"
│   ├── instructions/java.instructions.md     applyTo: "**/*.java"
│   ├── prompts/review.prompt.md
│   ├── skills/marker-skill/SKILL.md
│   └── agents/marker.agent.md
└── app/pom.xml                               <- only this project is imported

With the preference enabled (default), in a new chat each time:

  1. Ask mode: the response ends with [SRC-ROOT].
  2. With a .java file attached, the applyTo instruction is applied as well.
  3. Agent mode: typing / lists /review and the skill; sending /review applies the prompt file.
  4. Agent mode: the mode picker lists marker-agent; the agent can use the skill, and reading the root SKILL.md is auto-approved.
  5. With projects inferred from chat-attached files, attaching a file of app/ also loads the root instructions.
  6. Preferences → Custom Instructions: the project table lists repro (parent repository); Edit opens the root copilot-instructions.md.

Then uncheck the preference: none of the root customizations are used anymore, and the table row disappears immediately. The slash command list updates without restart, the agent picker on its next opening. A project whose root is the repository root behaves as before.

Open points

  • The preference is enabled by default. We could consider to disable it by default. But as it is now it works out of the box. Otherwise users would have to discover that they could enable in preferences ... kind of awkwards.

Eclipse projects are often nested inside a git repository, e.g. the modules
of a multi-module build, while .github/copilot-instructions.md and other
customization files live at the repository root. As the language server only
searches the workspace folders it receives, these files were ignored unless
the repository root itself was imported as a project.

For every workspace folder located inside a git repository, the folders up
to and including the repository root are now passed to the language server
as well, similar to VS Code's chat.useCustomizationsInParentRepositories.
This applies to chat requests (instructions, skills, sub-agents), slash
commands, custom agents, auto-approval of customization file reads and the
tool status of custom agents. A new preference on the Custom Instructions
page controls the behavior and is enabled by default.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The language server identifies prompt files by their file URI, but resolves
a slash command by the prompt's name. The completion popup showed and
inserted the URI, so selecting a prompt file did not apply it. Use the name
for prompt files, and omit the separator for templates without description.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…page

The project table only listed copilot-instructions.md files located in
project roots, so instructions loaded from a parent git repository were not
shown. While the parent repository preference is enabled, the table now also
lists the repository folders containing such a file, and Edit opens it.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@ArneDeutsch

Arne Deutsch (ArneDeutsch) commented Sep 29, 2026 •

Copy link
Copy Markdown
Author

@microsoft-github-policy-service agree company="itemis AG"

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot review overview

🟡 Changes recommended

The new checkbox may be invisible, parent agents are omitted from tool configuration, and asynchronous refreshes can restore stale parent files.

Review effort: Balanced
Findings: 1 High severity · 2 Medium severity

Open (3)
What changed in this PR

Adds optional discovery of Copilot customizations from parent Git repositories and fixes prompt-file slash commands.

Changes:

  • Extends workspace folders to parent repository roots.
  • Adds an enabled-by-default preference and UI.
  • Uses prompt names instead of URI identifiers for slash commands.
File Description
messages.properties Adds preference labels and parent-folder text.
Messages.java Exposes new localized strings.
LanguageServerSettingManager.java Refreshes customizations and extends tool-status scope.
CustomInstructionPreferencePage.java Adds preference control and parent instruction rows.
CopilotPreferenceInitializer.java Enables parent discovery by default.
ChatCompletionService.java Loads parent templates and uses command names.
ChatView.java Extends chat workspace folders.
ChatAssistProcessor.java Corrects prompt completion display and insertion.
LanguageServerSettingManagerTests.java Tests customization refresh events.
ChatCompletionServiceTest.java Tests prompt-name command handling.
WorkspaceUtils.java Implements repository-root discovery and folder expansion.
ConversationTemplate.java Adds template names and command-name resolution.
Constants.java Defines the preference key.
FileBasedCustomModeService.java Discovers agents in parent repositories.
CustomizationFileService.java Discovers parent customization files.
WorkspaceUtilsTests.java Tests repository traversal and preference behavior.
ConversationTemplateTests.java Tests slash-command name selection.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

- Ignore results of superseded customization file refreshes, so a refresh
  started before the parent repository preference was disabled cannot
  restore parent repository files afterwards.
- Resolve the folder of custom agents against the customization folders, so
  agents located in a parent repository are listed on the MCP and Custom
  Agents preference pages.
- Set a layout on the container of the parent repository checkbox.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot review overview

🟡 Changes recommended

Parent repository name collisions can configure the wrong custom agent, and the prompt popup regression lacks direct coverage.

Review effort: Balanced
Findings: 1 High severity · 1 Medium severity

Open (2)
Resolved since last review (2)
Previously missed (2)

In code that hasn't changed since last review

Medium severity Test leaks preference manager listener across tests

com.microsoft.copilot.eclipse.ui.test/​src/​com/​microsoft/​copilot/​eclipse/​ui/​preferences/​LanguageServerSettingManagerTests.java:349

This test attaches a newly constructed manager to the process-wide preference store and never removes it. The listener therefore survives the test and reacts to later preference changes, including the reset in finally, which can post extra events and make subsequent tests order-dependent. Isolate the test with the mock preference store (invoke the captured listener/property change directly), or explicitly unregister the manager and dispose it during cleanup.

Low severity Missing regression test for prompt proposal display and insertion

com.microsoft.copilot.eclipse.ui/​src/​com/​microsoft/​copilot/​eclipse/​ui/​chat/​ChatAssistProcessor.java:134

The regression fix is only tested through ChatCompletionService.isCommand; no test exercises this proposal-building path. A regression could still display or insert the prompt URI, or restore the dangling separator for an empty description, while the added tests pass. Add a focused ChatAssistProcessorTest or SWTBot probe that selects a prompt-file proposal and verifies /review is displayed/inserted with no - suffix.

- The MCP page keeps the mode IDs in the order of its mode selector
  entries instead of reconstructing a mode from its displayed label, which
  was ambiguous for parent repository folders with the same name.
- Custom agents located in a parent repository folder are labeled as such,
  or by the folder path if several of these folders have the same name.
- Unregister the settings manager created by a test, and test the display
  and insertion of prompt file completion proposals.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot review overview

🔵 Needs a closer look

Valid custom prompts named help or feedback are incorrectly filtered from slash commands.

Review effort: Balanced
Findings: 1 Medium severity

Open (1)
Resolved since last review (1)
Previously missed (1)

In code that hasn't changed since last review

Medium severity Exclude built-ins by ID, not prompt filename

com.microsoft.copilot.eclipse.ui/​src/​com/​microsoft/​copilot/​eclipse/​ui/​chat/​services/​ChatCompletionService.java:117

This now excludes user prompt files named help or feedback, because commandName() returns the prompt's name while its id is the file URI. EXCLUDED_COMMANDS is intended only to suppress the language server's IntelliJ-specific built-ins; preserving the original id check keeps those built-ins hidden without silently removing valid custom prompts.

@ArneDeutsch

Copy link
Copy Markdown
Author

Regarding "Exclude built-ins by ID, not prompt filename": filtering by the command name is intended. help and feedback are built-in commands of the language server, and it resolves built-in commands before prompt files, removing the /help keyword from the message. A prompt file named help or feedback therefore can't be invoked through its slash command; listing it would run the built-in command instead, which Eclipse hides on purpose.

@ArneDeutsch

Copy link
Copy Markdown
Author

This is for issue #101

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