Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -48,11 +48,11 @@ jobs:
- uses: actions/setup-python@v5
with:
python-version: "3.x"
- name: Emit skills (Copilot + Anthropic)
- name: Emit skills (Copilot + Anthropic + d365fo-cli)
run: python3 scripts/emit-skills.py
- name: Fail on untracked drift
run: |
if [ -n "$(git status --porcelain skills/copilot skills/anthropic)" ]; then
if [ -n "$(git status --porcelain skills/copilot skills/anthropic skills/d365fo-cli/references)" ]; then
echo "::error::skills/ artifacts drift from skills/_source. Run scripts/emit-skills.py locally and commit."
git status --porcelain skills/
exit 1
Expand Down
52 changes: 48 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -156,12 +156,56 @@ Full walkthrough: **[docs/SETUP.md](docs/SETUP.md)**

### GitHub Copilot (VS Code / Visual Studio)

Copy `.github/copilot-instructions.md` into your consuming repo's `.github/` folder. It contains the full X++ rule canon with MS Learn citations.
The preferred method is the **one-command skill installer** — it deploys the bundled `d365fo-cli` Copilot skill (SKILL.md + 19 lazily-loaded topic references) into your X++ project's `.github/skills/d365fo-cli/` folder. Copilot auto-discovers skills in `.github/skills/` with no extra configuration.

```powershell
# From the d365fo-cli repo's scripts folder:
.\Install-D365FoCopilotSkills.ps1 -XppRepo "K:\D365FO\MyProject"
```

The installer:
1. Regenerates `skills/d365fo-cli/references/` if needed, using whichever host is available (`pwsh`, Windows PowerShell, or `python`).
2. Copies `skills/d365fo-cli/SKILL.md` and all `references/*.md` to `<XppRepo>/.github/skills/d365fo-cli/`.
3. Removes reference files in the target that no longer exist upstream, so retired topics don't linger.
4. Prints a migration note if the legacy `copilot-instructions.md` / `instructions/` files still exist.

**Skill layout installed into your X++ repo:**

```sh
python3 scripts/emit-skills.py # emit instruction files
cp skills/copilot/*.instructions.md /your-repo/.github/instructions/
```
.github/
└── skills/
└── d365fo-cli/
├── SKILL.md # core rule canon + tool mapping (loaded when the skill activates)
└── references/ # 19 X++ topic files, loaded per topic on demand
├── coc-extension-authoring.md
├── xpp-database-queries.md
├── x++-class-authoring.md
├── xpp-class-and-method-rules.md
├── xpp-statement-and-type-rules.md
├── xpp-best-practice-rules.md
├── form-pattern-scaffolding.md
├── table-scaffolding.md
├── data-entity-scaffolding.md
├── event-handler-authoring.md
├── object-extension-authoring.md
├── security-hierarchy-trace.md
├── sysoperation-batch-patterns.md
├── business-events-authoring.md
├── custom-service-authoring.md
├── integration-patterns.md
├── label-translation.md
├── model-dependency-and-coupling.md
└── review-and-checkpoint-workflow.md
```

**Legacy path (pre-skill format):** If you previously used `copilot-instructions.md` + `instructions/*.instructions.md`, you can migrate by running the installer and then removing the old files:

```powershell
Remove-Item "<XppRepo>\.github\copilot-instructions.md" -ErrorAction SilentlyContinue
Remove-Item "<XppRepo>\.github\instructions" -Recurse -ErrorAction SilentlyContinue
```

The legacy `skills/copilot/*.instructions.md` output is still emitted by `emit-skills.ps1` / `emit-skills.py` for environments that cannot use the `.github/skills/` format (e.g. GitHub Copilot versions that predate skill auto-discovery).

### Claude Code / Claude Desktop

Expand Down
6 changes: 4 additions & 2 deletions docs/CAPABILITIES.md
Original file line number Diff line number Diff line change
Expand Up @@ -375,7 +375,9 @@ d365fo-mcp --http --port 8080

## Copilot Skills

19 instruction files in `skills/copilot/` cover the full X++ authoring and review canon. Deploy to an X++ project with the `Install-D365FoCopilotSkills.ps1` script (see [SETUP.md](SETUP.md)).
The `d365fo-cli` agent skill (`skills/d365fo-cli/`) covers the full X++ authoring and review canon: `SKILL.md` holds the rule canon and tool mapping, and 19 topic files in `references/` are loaded on demand. Deploy to an X++ project with the `Install-D365FoCopilotSkills.ps1` script (see [SETUP.md](SETUP.md)), which installs it to `.github/skills/d365fo-cli/`.

The same 19 topics are also emitted as `skills/copilot/*.instructions.md` (legacy `applyTo` format) and `skills/anthropic/<id>/SKILL.md` (Claude Code / Claude Desktop).

| Skill | Covers |
|-------|--------|
Expand Down Expand Up @@ -449,4 +451,4 @@ d365fo-mcp --http --port 8080
| `src/D365FO.Cli/Commands/` | All CLI command implementations |
| `src/D365FO.Mcp/ToolCatalog.cs` | MCP tool descriptors |
| `src/D365FO.Mcp/ToolHandlers.cs` | MCP handler methods |
| `skills/_source/` | Skill source files (emitted to `skills/copilot/`) |
| `skills/_source/` | Skill source files (emitted to `skills/d365fo-cli/references/`, `skills/copilot/`, `skills/anthropic/`) |
7 changes: 3 additions & 4 deletions docs/EXAMPLES.md
Original file line number Diff line number Diff line change
Expand Up @@ -718,12 +718,11 @@ d365fo agent-prompt --out .prompts/d365fo.md

### GitHub Copilot (VS Code / Visual Studio)

```sh
cp skills/copilot/* .github/instructions/
d365fo agent-prompt --out .github/copilot-instructions.md
```powershell
.\scripts\Install-D365FoCopilotSkills.ps1 -XppRepo "K:\D365FO\MyProject"
```

Copilot picks up `.github/instructions/*.instructions.md` via `applyTo` globs and drives `d365fo` through its terminal tool.
Copilot auto-discovers `.github/skills/d365fo-cli/` and loads the skill on demand — no extra configuration needed. It drives `d365fo` through its terminal tool.

### Claude Code / Claude Desktop

Expand Down
6 changes: 3 additions & 3 deletions docs/MIGRATION_FROM_MCP.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,13 +35,13 @@ Be aware of the cost: keeping MCP registered injects its full schema overhead (~

### Path A — side-by-side operation (mixed environments / migration)

The existing `.mcp.json` and `copilot-instructions.md` stay unchanged. The CLI is added alongside:
The existing `.mcp.json` stays unchanged. The CLI is added alongside:

1. Build and deploy the CLI — see [SETUP.md](SETUP.md).
2. Copy `skills/copilot/*.instructions.md` to `.github/instructions/` in your X++ project.
2. Run `scripts/Install-D365FoCopilotSkills.ps1 -XppRepo <your-xpp-repo>` to deploy the `d365fo-cli` Copilot skill.
3. Copilot automatically uses the shell tool for CLI commands and MCP for tool calls — both from the same index.

> **Heads-up — `copilot-instructions.md` collision.** The per-topic skills in `.github/instructions/*.instructions.md` have unique filenames and coexist fine. But both the CLI and `d365fo-mcp-server` ship a top-level `.github/copilot-instructions.md` and install it with `Copy-Item -Force`, so it's last-installer-wins, not a merge — re-running the other installer clobbers it again. Keep **one** canon file: the CLI's, which is the schema-v5 superset and already documents the shell-first flow plus a no-shell fallback. You don't need the MCP server's instruction file for its tools to work — MCP tools are registered via `.mcp.json` and their schemas are self-describing; the instruction file only guides behaviour, it doesn't enable the tools.
> **Heads-up — conflict with old MCP instruction files.** If you previously deployed `.github/copilot-instructions.md` from `d365fo-mcp-server`, remove it — the new `d365fo-cli` Copilot skill supersedes it. The skill format avoids the file collision: `.github/skills/d365fo-cli/` coexists with any other skills without clobbering.

### Path B — CLI only

Expand Down
14 changes: 7 additions & 7 deletions docs/SETUP.md
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ Or run the daemon and forget about it — `d365fo daemon start` keeps the SQLite

```mermaid
flowchart LR
Cop["GitHub Copilot<br/>VS 2022/2026 · VS Code"] -->|.github/instructions/| Bin
Cop["GitHub Copilot<br/>VS 2022/2026 · VS Code"] -->|.github/skills/d365fo-cli/| Bin
Cla["Claude Code<br/>CLI · VS Code ext."] -->|skills/anthropic/| Bin
Other["Codex · Gemini · Cursor"] -->|AGENTS.md| Bin
Mcp["Claude Desktop · Continue<br/>(MCP host)"] -->|JSON-RPC stdio| Mbin["d365fo-mcp"]
Expand All @@ -154,17 +154,17 @@ flowchart LR
### GitHub Copilot — Visual Studio 2022 / 2026 / VS Code (agent mode)

1. Place `d365fo` on `PATH` (either Option 1 alias or Option 2 binary above).
2. Deploy the Skills into a parent folder of your X++ solutions:
2. Deploy the `d365fo-cli` Copilot skill into a parent folder of your X++ solutions:

```powershell
.\scripts\Install-D365FoCopilotSkills.ps1 `
-CliRepo C:\source\d365fo-cli `
-XppRepo K:\D365FO\MyProject
```

The script copies `.github/copilot-instructions.md` and all `skills/copilot/*.instructions.md` files. One copy in a common parent covers every solution beneath it — VS searches upward from the `.sln`.
The script deploys `skills/d365fo-cli/SKILL.md` and all `references/*.md` to `.github/skills/d365fo-cli/`. One copy in a common parent covers every solution beneath it — VS searches upward from the `.sln`. Copilot auto-discovers skills in `.github/skills/` with no extra configuration.
3. **Agent mode (recommended).** Open Copilot Chat → mode dropdown (top-right) → **Agent**. Copilot now calls `d365fo` directly via its terminal tool — no copy-paste.
4. **Chat mode (fallback).** Without agent tools, Copilot asks you to run `d365fo` commands in Developer PowerShell and paste the JSON back. The Skills teach Copilot to ask first — if it skips that step the `.github/copilot-instructions.md` file is missing from the parent folder.
4. **Chat mode (fallback).** Without agent tools, Copilot asks you to run `d365fo` commands in Developer PowerShell and paste the JSON back. The skill teaches Copilot to ask first — if it skips that step the `.github/skills/d365fo-cli/SKILL.md` file is missing from the parent folder.

> ⚠️ **Never** use `@workspace` or built-in code search on AOT XML. It always fails. Copilot must use `d365fo` exclusively for codebase queries; the Skills enforce this.

Expand All @@ -173,9 +173,9 @@ flowchart LR
> | Term | What it controls | Set via |
> |---|---|---|
> | `D365FO_WORKSPACE_PATH` (CLI env var) | Where `d365fo generate` writes scaffolded X++ files | `d365fo init` / `settings.json` / env var |
> | Editor "workspace" (VS solution root / VS Code opened folder) | Where Copilot looks for `.github/copilot-instructions.md` and `.github/instructions/*.instructions.md` | Which folder/`.sln` you open in the IDE |
> | Editor "workspace" (VS solution root / VS Code opened folder) | Where Copilot looks for `.github/skills/d365fo-cli/SKILL.md` | Which folder/`.sln` you open in the IDE |
>
> Setting `D365FO_WORKSPACE_PATH` (or any `D365FO_*` env var) has **zero effect** on Copilot's instruction discovery. If Copilot isn't finding your instructions, the fix is always about **which folder is open in the editor**, never about CLI configuration — re-run `Install-D365FoCopilotSkills.ps1` against the actual parent folder you open, not against `D365FO_WORKSPACE_PATH`.
> Setting `D365FO_WORKSPACE_PATH` (or any `D365FO_*` env var) has **zero effect** on Copilot's skill discovery. If Copilot isn't finding your skill, the fix is always about **which folder is open in the editor**, never about CLI configuration — re-run `Install-D365FoCopilotSkills.ps1` against the actual parent folder you open, not against `D365FO_WORKSPACE_PATH`.

### Claude Code (CLI or VS Code extension)

Expand Down Expand Up @@ -280,7 +280,7 @@ d365fo doctor
| `UNSUPPORTED_PLATFORM` | `build` / `sync` / `test` / `bp` require Windows + a D365FO dev VM. Everything else still works |
| `NO_INDEX` | `d365fo index build && d365fo index extract` |
| `stale-index` warning from `doctor` | `d365fo index refresh --model <Model>` (or just start the daemon) |
| Copilot Chat says "There was an error executing code search" then writes generic X++ | VS Copilot Chat cannot search AOT XML — `.github/copilot-instructions.md` must be deployed in a parent folder. Re-run `Install-D365FoCopilotSkills.ps1` and restart VS. For full automation switch Copilot Chat to **Agent** mode |
| Copilot Chat says "There was an error executing code search" then writes generic X++ | VS Copilot Chat cannot search AOT XML — the `d365fo-cli` skill must be deployed in a parent folder. Re-run `Install-D365FoCopilotSkills.ps1` and restart VS. For full automation switch Copilot Chat to **Agent** mode |
| Index file appears locked | Stop any running `d365fo daemon` or `d365fo-mcp` process; `-wal` / `-shm` sidecar files are normal |
| Settings differ between Developer PowerShell and PowerShell 7 | Re-run `d365fo init --persist-profile` — it writes both profiles and the JSON config |
| Self-contained binary won't start on Linux | `chmod +x d365fo` after copying out of the publish folder |
Expand Down
2 changes: 1 addition & 1 deletion docs/TOKEN_ECONOMICS.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ flowchart LR
MCP -.->|same backing index| CLI
```

Every MCP request loads all tool schemas into the model context — there is no "load on demand". The CLI exposes one shell tool; the agent discovers commands via `d365fo schema` only when it needs them. Skills add ~30–60 tokens of frontmatter per `.instructions.md` file; the full skill body is only paged in when the agent decides it is relevant.
Every MCP request loads all tool schemas into the model context — there is no "load on demand". The CLI exposes one shell tool; the agent discovers commands via `d365fo schema` only when it needs them. The `d365fo-cli` agent skill costs only its `name` + `description` frontmatter until the agent decides it is relevant; the `SKILL.md` body is paged in on activation, and the 19 `references/*.md` topic files only when that topic actually comes up. (In the legacy `.instructions.md` layout the equivalent standing cost was ~30–60 tokens of frontmatter per file.)

> **Tool consolidation cut the MCP baseline too.** The upstream `d365fo-mcp-server`
> collapsed its old per-type surface (~61 tools, ~2,900 tok of schemas) into 26
Expand Down
10 changes: 5 additions & 5 deletions docs/TROUBLESHOOTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -239,18 +239,18 @@ These are two completely unrelated concepts that happen to share the word "works
| Term | What it controls |
|---|---|
| `D365FO_WORKSPACE_PATH`, `D365FO_PACKAGES_PATH`, `D365FO_CUSTOM_PACKAGES_PATH` (CLI env vars) | Where the `d365fo` CLI indexes metadata from / writes scaffolded output to |
| The folder/`.sln` open in Visual Studio or VS Code ("workspace" in the IDE sense) | Where Copilot looks for `.github/copilot-instructions.md` and `.github/instructions/*.instructions.md` |
| The folder/`.sln` open in Visual Studio or VS Code ("workspace" in the IDE sense) | Where Copilot looks for `.github/skills/d365fo-cli/SKILL.md` |

No `D365FO_*` environment variable or `settings.json` entry has any effect on Copilot's instruction discovery. Copilot (both in Visual Studio and VS Code) only walks **upward from the folder/solution you actually opened in the editor** looking for a `.github/` folder — it never reads CLI configuration.

Fix, in order:

1. Confirm which folder is actually open in the editor (Visual Studio: the `.sln`'s folder; VS Code: File → Open Folder).
2. Re-run `Install-D365FoCopilotSkills.ps1` targeting that exact folder (or a parent of it) as `-XppRepo`, not the `D365FO_WORKSPACE_PATH` / `D365FO_CUSTOM_PACKAGES_PATH` value.
3. Visual Studio only: enable **Tools → Options → GitHub Copilot → Copilot Chat → "Enable custom instructions to be loaded from .github/copilot-instructions.md files and added to requests."**
4. No shared parent solution/`.sln` above your projects? Use the global fallback instead of per-project copies:
- Visual Studio: concatenate `skills/copilot/*.instructions.md` into `%USERPROFILE%\copilot-instructions.md` (applies to every solution, but loses `applyTo` scoping).
- VS Code: point `chat.instructionsFilesLocations` at one shared folder containing the `*.instructions.md` files (keeps `applyTo` scoping).
3. Visual Studio only: confirm the **GitHub Copilot** extension is enabled and skills auto-discovery is active (look for the `.github/skills/` folder being picked up in Copilot Chat's reference list).
4. No shared parent solution/`.sln` above your projects? Copy the skill to a higher common ancestor folder:
- Run `Install-D365FoCopilotSkills.ps1 -XppRepo <common-parent>` to place `.github/skills/d365fo-cli/` where Copilot can walk up to it from any solution.
- Legacy fallback (pre-skill hosts): `skills/copilot/*.instructions.md` are still emitted and can be placed in `.github/instructions/` as before.
5. Verify: after Copilot answers, expand **References / "Used N references"** in the reply — loaded instruction files are listed there. If your file isn't listed, it wasn't discovered.

---
Expand Down
2 changes: 1 addition & 1 deletion docs/img/solution-architecture-diagram.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Loading