-
Notifications
You must be signed in to change notification settings - Fork 2
Interop Matrix
VS Code Copilot has grown to read most of Claude Code's configuration natively. FeatherSpec leans on that overlap: rules, the constitution, the workflow bodies and the Memory Bank are single files that both tools read. Only genuinely tool-specific things stay separate.
| Artifact | Claude Code | VS Code Copilot | Caveats |
|---|---|---|---|
AGENTS.md (constitution) |
via @AGENTS.md import in CLAUDE.md
|
native, chat.useAgentsMdFile (default on) |
the single source of truth for both |
CLAUDE.md |
native | native, chat.useClaudeMdFile (default on) — off here on purpose |
we point Copilot straight at AGENTS.md, so the one-line import file is redundant for it |
.claude/rules/*.md (paths:) |
native, loads when a matching file is read | not read directly — reached through six thin loaders in .github/instructions/
|
VS Code cannot read instruction files from .claude/rules, whatever the custom instructions page once suggested. Each rule ships a <name>.instructions.md loader whose applyTo: mirrors the rule's paths: globs and whose body is one pointer at the .claude/rules file — the rules stay single-source, the loaders hold none of their own |
.claude/commands/<name>.md (workflow body) |
native, /<name> from the file name; disable-model-invocation: true keeps the description out of context |
not read directly — reached through the .github/prompts loader below |
the body is written once and both tools execute the same text |
.github/prompts/<name>.prompt.md (loader) |
— (ignored) | native, /<name>; .github/prompts is the default location and the .prompt.md extension is required |
a prompt file is user-invoked only, never offered to the model; each loader is a link to the body and holds no rules |
| Web research from inside a workflow | native WebSearch (US-only) and WebFetch
|
built-in #fetch for a page, plus the web tool in agent mode |
/sdd-plan asks for "your web search or fetch capability" rather than naming a tool, and requires the model to say so when none is available instead of guessing |
.github/agents/*.agent.md |
— (kept Copilot-only, see below) | native — .github/agents is a default location (chat.agentFilesLocations) |
a Copilot custom agent is a selectable persona — or, with user-invocable: false, a subagent-only worker like sdd-scout
|
Subagent delegation (the scan's sdd-scout) |
native — .claude/agents/sdd-scout.md is a project subagent with its own context window |
native — .github/agents/sdd-scout.agent.md runs as a subagent; the calling agent needs the agent tool |
the frontmatter dialects are incompatible (comma-separated tools string vs. YAML array), so the scout ships once per dialect with a byte-identical body; environments that cannot delegate use the scan body's documented sequential fallback |
hooks in .claude/settings.json
|
native (with matchers) | reads .claude/settings.json, .claude/settings.local.json and ~/.claude/settings.json; parses Claude's format |
VS Code ignores matcher values — hooks run on all tool invocations, so a shared hook must filter on tool_name in the script |
| Artifact | Claude Code | VS Code Copilot |
|---|---|---|
| The slash-command entry point | .claude/commands/*.md |
.github/prompts/*.prompt.md — different folder and extension, so one file cannot serve both; FeatherSpec ships a one-line Copilot loader per command and keeps the body in .claude/commands/
|
Agent skills (.claude/skills/<name>/SKILL.md) |
native, /<name>
|
native, .claude/skills is a default location |
!`shell` injection, $ARGUMENTS, $0/$1
|
supported |
not supported — the documented mechanism is ${input:…} — so the shared bodies use neither |
Everything in .claude/settings.json except hooks (autoMemoryEnabled, permissions, …) |
native | no documented support (treat as ignored) |
| MCP servers |
.mcp.json, root key mcpServers
|
.vscode/mcp.json, root key servers
|
| Auto memory |
~/.claude/projects/<project>/memory/ — shipped off via autoMemoryEnabled: false
|
the copilot-chat extension's local memory tool — shipped off via github.copilot.chat.tools.memory.enabled: false (caveats below) |
| Output styles, plugins/marketplaces | Claude-specific | Copilot-specific |
Every location above is already a VS Code default, so a fresh clone works untouched. The shipped settings file restates them — and deliberately flips a few — so the setup survives a changed default or a workspace that overrode one:
{
"chat.useAgentsMdFile": true,
"chat.useClaudeMdFile": false,
"chat.instructionsFilesLocations": { ".github/instructions": true, ".claude/rules": false },
"chat.promptFilesLocations": { ".github/prompts": true },
"chat.agentFilesLocations": { ".github/agents": true, ".claude/agents": false },
"github.copilot.chat.tools.memory.enabled": false
}.claude/rules is explicitly off: VS Code cannot read instruction files from that folder, so
the path-scoped rules reach Copilot through the .github/instructions loaders instead —
pointing the location at the folder anyway could only surface files in a dialect VS Code does
not parse.
github.copilot.chat.tools.memory.enabled: false is the Copilot counterpart to
autoMemoryEnabled: false in .claude/settings.json: it disables the copilot-chat
extension's local memory tool, which otherwise writes memory files into the extension's
storage and auto-injects them into every session. Honest caveat: some bundled builds of the
extension lack the setting key entirely, and vscode #318131 (open) reports memory writes
despite the setting — treat it as a mitigation, not a guarantee. The actual guard is the
constitution's preference-capture rule: a preference claimed by tool memory is proposed and
asked about, never silently followed.
.claude/agents is a flip: VS Code also reads Claude-format agent files from that folder,
and it now contains the deep scan's scout in Claude dialect — loading it would surface a
duplicate scout whose tools string VS Code cannot interpret, i.e. a second scout with an
unrestricted tool set. See the asymmetry below.
.github/agents/SpecDrivenAgent.agent.md is kept Copilot-only on purpose. VS Code would also
read a .claude/agents/ file, but the semantics differ:
- In Copilot, a custom agent is a persona you pick from a dropdown — it shapes the same conversation you are already in.
- In Claude Code, a
.claude/agents/file is an isolated subagent with its own context window that does not share your conversation.
Same file location, different meaning. Claude Code has no persona picker, and that is fine: the
persona there is AGENTS.md (always loaded via @AGENTS.md) plus /sdd-overview for the
greeting and the map.
The deep scan sharpened this asymmetry: its sdd-scout must exist for both tools, so it ships
twice with a byte-identical body — .claude/agents/sdd-scout.md (Claude dialect: subagent,
comma-separated tools string) and .github/agents/sdd-scout.agent.md (VS Code dialect: YAML
tools array plus user-invocable: false, so it never appears in the persona dropdown and is
only reachable as a subagent). Both files carry an annotation naming the other; change them
together. This pair is why the shipped settings turn .claude/agents off for VS Code.
VS Code: custom instructions · agent skills · custom agents · hooks · agent tools · settings reference. Claude Code: skills · memory/rules.
Start here
Reference
Design & interop
- Interop Matrix
- Design Decisions
- Specify Method
- Committing to One Tool
- Migrating from the predecessor
- Releasing
Help