Prompt Files & Slash Commands

This content was generated with the assistance of AI and should be verified against the official documentation of each tool and framework before being relied on in production.

This section’s bibliography lists the reference material consulted while preparing these pages.

Examples on this page target the Claude Code CLI 2.1.283 and VS Code 1.139 with the GitHub Copilot Chat extension, checked against the official Claude Code and VS Code/Copilot documentation as of 2026-09-28. The ai-catalog excerpts elsewhere in this sub-section are pinned to commit 58fb709; ai-catalog has no prompt files or Copilot files on main as of that commit, so this page’s examples are written for the same DocsAssistant API Spring Boot sample used across the AI section rather than excerpted from the catalog. The running task is a reusable "scaffold a new endpoint" prompt, so the same procedure can be replayed for any route instead of being retyped by hand each time.

A prompt file (Copilot) or a custom command (Claude Code) is the simplest of this sub-section’s surfaces: a single Markdown file that turns a paragraph you would otherwise retype into something you invoke by name. Both tools also let the assistant write one for you from an ongoing conversation — covering that generation flow belongs to each product’s own tutorial, linked below; this page covers the file format and how to use it once it exists.

GitHub Copilot prompt files

A prompt file is a Markdown file with the .prompt.md extension, saved under the workspace’s .github/prompts folder or at the user level (available across every workspace). As of 2026-09-28 its optional YAML frontmatter supports:

Field Required What it does

description

No

A short description of the prompt, shown in prompt pickers.

name

No

The name typed after / in chat. Defaults to the file name.

argument-hint

No

Hint text shown in the chat input field to guide how to invoke the prompt.

agent

No

Which agent runs the prompt: ask, agent, plan, or a custom agent’s name. Defaults to the current agent, or to agent when tools is set.

model

No

The language model to use. Defaults to the currently selected model.

tools

No

The built-in tools, tool sets, MCP tools or extension-contributed tools available to the prompt. A tool not currently available is silently ignored.

.github/prompts/new-endpoint.prompt.md
---
description: 'Scaffold a new DocsAssistant API REST endpoint with a repository lookup and tests'
agent: 'agent'
tools: ['edit', 'search', 'execute']
---
Add a new endpoint to `DocsController` (`src/main/java/com/example/docsassistant/`):

- HTTP method and path: ${input:route:HTTP method and path, e.g. GET /api/pages/42}
- Behavior: ${input:behavior:What should it return, and what happens when the lookup misses?}

Follow the existing controller's style: use `PageRepository` for lookups, map results with
`PageDto.from(Page)`, and return a `ProblemDetail` for the not-found case. Add a JUnit test for both the
success and the not-found path, then run the project's tests.

Typing /new-endpoint in the Copilot Chat view (in VS Code, Visual Studio or a JetBrains IDE) inserts the prompt, switches to the agent chat agent if it wasn’t already selected, and, because of the ${input:...} placeholders, prompts for route and behavior before sending. The tools entries are VS Code tool sets: edit and search for the file work, and execute for running the tests in the terminal. A placeholder’s hint text avoids braces, because the first } closes the placeholder. See GitHub — Create your first prompt file and VS Code — Prompt files.

As of 2026-09-28, VS Code’s documentation states that prompt files are deprecated for Agent Host sessions and are not loaded there at all; they keep working with the older Local agent for now, but that agent is scheduled for removal in a future release. VS Code also offers an experimental prompt file migration that converts a workspace’s or user’s prompt files into Agent Skills, but it is not generally available: it ships only in VS Code Insiders, is controlled by the chat.customizations.promptMigration.enabled setting (on by default there), and its Convert to Skills…​ card appears in the Agent Customizations editor only once an Agent Host is selected in the Chat view. On stable VS Code the conversion has to be done by hand. Any new reusable Copilot procedure is worth authoring (or migrating) as a skill for this reason alone — see Skills and VS Code — Migrate prompt files to skills.

Claude Code custom commands

A custom command is a Markdown file under the project’s .claude/commands/ directory (or the user-level equivalent). As of 2026-09-28, Claude Code’s own documentation describes commands and skills as unified rather than as two separate mechanisms:

Custom commands have been merged into skills. A file at .claude/commands/deploy.md and a skill at .claude/skills/deploy/SKILL.md both create /deploy and work the same way. Your existing .claude/commands/ files keep working.
— code.claude.com/docs/en/skills
as of 2026-09-28

Concretely: the Skills page calls a command file "the older format". It still supports the same frontmatter fields as a skill’s SKILL.md (description, argument-hint, allowed-tools, model, disable-model-invocation, and so on) except name (the file name supplies it) and paths. Being a single file, it also can’t carry a skill’s supporting files. Nothing already written as a command needs to move; a skill is only worth the extra directory when the procedure needs files alongside it — see Skills for the full frontmatter reference and anatomy.

.claude/commands/new-endpoint.md
---
description: Scaffold a new DocsAssistant API REST endpoint with a repository lookup and tests
argument-hint: "[http-method] [path]"
allowed-tools: Bash(mvn test), Edit, Write
---
Add a $0 endpoint at $1 to `DocsController` (`src/main/java/com/example/docsassistant/`). Follow the
existing controller's style: use `PageRepository` for lookups, map results with `PageDto.from(Page)`, and
return a `ProblemDetail` for the not-found case. Add a JUnit test for both the success and the not-found
path, then run `mvn test`.

Extra notes from the caller: $ARGUMENTS

Running /new-endpoint GET /api/pages/{id} expands $0 to GET, $1 to /api/pages/{id}, and $ARGUMENTS to the full GET /api/pages/{id} string, so the last line repeats the whole input as typed. The argument-hint value is quoted because an unquoted value starting with [ is parsed as a YAML list and the frontmatter fails to parse; Claude Code then loads the command with no fields set. As of 2026-09-28, Claude Code’s argument substitutions are:

Placeholder Expands to

$ARGUMENTS

Everything typed after the command name, as one string. If nothing in the body uses a placeholder, Claude Code appends it anyway as ARGUMENTS: <value>, so the input is never silently dropped.

$0, $1, … (or $ARGUMENTS[0], $ARGUMENTS[1], …)

One argument by 0-based position ($0 is shorthand for $ARGUMENTS[0], the first argument; $1 is the second). Quote a multi-word argument (/new-endpoint GET "/api/pages/{id}") to keep it as one positional value. An index with no matching argument is left in the output unchanged.

$name

A named argument declared in an arguments: frontmatter list, mapped to argument positions in order. A named argument with no matching value expands to an empty string.

A literal $1 or $ARGUMENTS in prose is escaped with a backslash (\$1) so it isn’t expanded. See Claude Code — Skills (which documents both the merge and the argument substitutions) and Claude Code — Commands for the built-in, non-custom commands such as /compact and /rewind.

In Claude Code
$ claude
> /new-endpoint GET "/api/pages/{id}"
In GitHub Copilot (VS Code)
/new-endpoint
> route: GET /api/pages/{id}
> behavior: Return the page as a PageDto, or a 404 with a JSON error body when the id doesn't exist.

Both invocations drive the same underlying task — scaffold one endpoint following the existing controller’s conventions — but get there differently: Claude Code’s positional $0/$1 take the route split across two words typed on the command line, while Copilot’s ${input:...} fields open interactive prompts after / runs.

When a prompt file or command is enough, and when you need a skill

If you need… A prompt file / command is enough, or you need a skill

A single reusable procedure invoked by typing its name

A prompt file or command is enough — that’s the whole feature.

Supporting files alongside the instructions (reference docs, scripts, templates, example output)

You need a skill. A prompt file and a Claude Code command are single files; only a skill’s directory (.claude/skills/<name>/, or Copilot’s .github/skills/<name>/) can hold them. See Skills.

The assistant deciding on its own to run the procedure, from the conversation, without you typing its name

For Copilot, you need a skill: a prompt file is always run manually — "unlike custom instructions that are applied automatically, you invoke prompt files manually in chat" (VS Code’s own description). For Claude Code, either works: a command’s description is matched for model-invoked triggering exactly like a skill’s, unless disable-model-invocation: true restricts it to you.

Pre-approving specific tools so the assistant isn’t stopped to ask

Either works, with a caveat. A Claude Code command supports allowed-tools exactly like a skill. A Copilot prompt file’s tools: field only scopes which tools are offered to the prompt — it is not a permission auto-approval, so tool use still goes through the workspace’s own approval settings.

Running the procedure in an isolated context (so it can’t see, or pollute, the rest of the conversation)

In Copilot you need a skill with context: fork (experimental in VS Code); a prompt file can’t fork. In Claude Code a command file accepts context: fork just as a skill does, since it takes every skill field except name and paths. The trade-offs are compared on Subagents & Custom Agents.

In short: reach for a prompt file or a Claude Code command first, since either is a single Markdown file to write and version. Move to a skill only once the procedure needs files beside it, or, on Copilot, needs to trigger itself from context instead of a typed name or needs the isolation a forked context provides.