Copilot CLI is an agent in your terminal. It reads your repository, runs commands, edits files, calls GitHub, and asks permission before doing anything that touches your system.
That last property is what makes it the best surface for learning how agents should be operated: the permission model is explicit, visible, and yours to configure.
Installing and starting
Section titled “Installing and starting”Copilot CLI runs on Linux, macOS, and Windows via PowerShell or the Windows Subsystem for Linux.
copilotWhat it doesStarts an interactive Copilot CLI session in the current directory.
Why we run itThe interactive session is the primary mode; the current directory determines what it can see by default.
Expected resultAn interactive interface. If you are not signed in you will be prompted to run /login.
Authentication uses OAuth:
copilot login--web-flow forces browser-based authentication, --device-code forces the device flow, and
--with-token reads a token from standard input. --host targets a GitHub Enterprise instance.
For non-interactive use — a script, a CI step, a one-off — the -p form runs a single prompt:
copilot -p "Show me this week's commits and summarize them" --allow-tool='shell(git)'Note the explicit allowance. Non-interactive mode cannot prompt for approval, so anything it needs must be permitted up front — which forces you to state what the task requires.
The permission model
Section titled “The permission model”The most important part of this article. Every tool use that touches your filesystem or runs a command requires approval.
| Control | Effect |
|---|---|
| Approve once | This call only |
| Approve for session | This class, for this session |
--allow-tool='shell(git)' | Pre-approve a specific tool class |
--deny-tool=... | Refuse regardless |
--allow-all-tools | Approve everything |
/allow-all or /yolo | The same, from inside a session |
/permissions | Manage permissions and trust settings |
The narrow allowance is the one to reach for. --allow-tool='shell(git)' lets an agent run Git freely
while still asking before anything else — which keeps a Git-heavy session fast without giving away the
boundary.
Sessions and slash commands
Section titled “Sessions and slash commands”Inside a session, slash commands manage the environment rather than the conversation. The current list
is always /help; these are the ones that recur.
| Command | Does |
|---|---|
/help | The authoritative current command list |
/login | Authenticate |
/model | Display or set the model |
/context | Context window usage and visualisation |
/compact | Summarise history to reclaim context |
/clear, /new, /reset | Start a new conversation |
/session | Create, name and manage sessions |
/resume | Reopen a previous session |
/cwd, /cd | Change or show the working directory |
/add-dir PATH | Allow access to a directory, loading its .github/skills and .github/agents |
/agent | Browse and select available agents |
/plan | Planning mode for multi-step work |
/review [FILE] | Review code changes or file contents |
/diff | Review changes in the current directory |
/mcp | Manage MCP server connections |
/permissions | Manage permissions and trust |
/tools | Manage available tools |
/env | Show loaded instructions, MCP servers, skills, agents, hooks, plugins |
/sandbox | Manage sandboxed execution |
/delegate | Delegate changes to a remote repository with a generated pull request |
/fleet | Parallel subagent execution |
/share | Generate or redeem session share codes |
Four are worth knowing before you need them.
/env shows everything currently loaded — instructions, skills, agents, hooks, MCP servers,
plugins. This is the first command to run when behaviour is unexpected, because “is my configuration
even loaded” is the most common answer.
/context shows window usage. A session getting vaguer is usually a full window, and this is how
you confirm it rather than guessing.
/add-dir brings another directory into scope and loads its skills and agents. That is a scope
decision as much as a convenience — you are granting file access and adopting configuration at the same
time.
/plan produces an approach before actions. The cheapest intervention point in any agentic
interaction.
The default mode acts; plan mode, reachable with Shift+Tab, collaborates on the approach first.
The rule from agent mode applies identically: correcting a plan costs a sentence; correcting six edited files costs a review. For anything where the approach is not obvious, plan first.
Configuration the CLI reads
Section titled “Configuration the CLI reads”Copilot CLI reads repository configuration, which means the work you did in the Copilot cluster applies here.
Instructions — AGENTS.md, .github/copilot-instructions.md and CLAUDE.md, plus path-specific
instructions and personal instructions from ~/.copilot/. File references with @ followed by a
relative path let one file include another rather than duplicating content.
Custom agents — specialised personas with restricted tools. See Custom Agents.
Agent skills — loaded when relevant, from .github/skills/ among other locations, with personal
skills in ~/.copilot/skills/ or ~/.agents/skills/.
Hooks — deterministic lifecycle control from .github/hooks/*.json. The only mechanism here that
enforces.
MCP servers — external tools and data.
Plugins — bundles of the above, managed with copilot plugin and copilot plugins.
copilot init initialises custom instructions for a repository, which is a reasonable starting point
if you have none.
copilot plugins listWhat it doesLists every plugin, MCP server, skill, instruction source and language server currently configured, without entering a session.
Why we run itIt answers 'what is actually loaded' from outside a session, which is the fastest way to diagnose configuration that seems inert.
Expected resultGrouped text, or JSON with --json.
--kind filters to mcp, skill, instruction, plugin or lsp, and --json makes it scriptable.
Managing skills, agents and MCP
Section titled “Managing skills, agents and MCP”Three command families for the configuration surface:
{/* List, add and remove agent skills */}copilot skill{/* Manage MCP server configurations */}copilot mcp{/* Enable, disable or remove a plugin, MCP server or skill */}copilot plugins enable NAME --skillcopilot plugins disable NAME --mcpcopilot plugins remove NAME --pluginThe enable and disable operations are useful for diagnosis: turning something off and seeing whether behaviour changes is more reliable than reasoning about what a piece of configuration is doing.
Hooks: the enforcement layer
Section titled “Hooks: the enforcement layer”Everything else the CLI reads influences behaviour. Hooks control it, which makes them the most important configuration on this page for anything that must not happen.
A hook is defined in .github/hooks/*.json:
{ "version": 1, "hooks": { "preToolUse": [ { "type": "command", "bash": "scripts/check-tool-use.sh", "timeoutSec": 10 } ] }}The events include sessionStart, sessionEnd, userPromptSubmitted, preToolUse, postToolUse,
postToolUseFailure, agentStop, subagentStart, subagentStop, errorOccurred, notification and
permissionRequest.
preToolUse is the one that matters. It runs before the agent uses any tool and can approve or deny
the call. A command hook denies by writing a decision to stdout:
{ "permissionDecision": "deny", "permissionDecisionReason": "Reason shown to the agent"}For command hooks, exit code 2 is treated as a deny, and the tool call is blocked. Non-timeout
errors also fail closed for preToolUse — which is the correct default for a security control and
worth knowing, because a broken hook script blocks rather than passes.
Hooks can also be http — posting to a URL — or prompt, which auto-submits text at session start.
The practical uses: blocking commands touching production paths, requiring a secret scan before a commit, logging tool use for audit, and enforcing organisation policy that instructions can only request. Building Repository AI Agents covers the design properly.
Credentials and environment
Section titled “Credentials and environment”The security consideration specific to this surface.
The CLI runs in your shell. It inherits your environment variables, your cloud CLI sessions, your
kubectl context and whatever your credential helper will hand over.
That is convenient — it is why the CLI can do useful work without configuration — and it means the agent’s effective permissions are your permissions.
The rules:
Do not run it in a shell with production credentials loaded. No task in this cluster requires them.
Know your context before letting it run context-sensitive commands. kubectl config current-context
and the cloud equivalent, before rather than after.
Prefer read-only credentials for anything diagnostic, which is most of what you will do.
Use a scoped, expiring token where a token is needed at all, following fine-grained tokens.
Delegating and parallelising
Section titled “Delegating and parallelising”Two commands that change the shape of what the CLI can do, and both deserve care.
/delegate hands work to a remote repository, producing a generated pull request. That is the CLI
entry point to delegation — the same model as the
cloud agent, started from your terminal rather than from an issue.
The distinction worth holding: everything else in the CLI happens on your machine and you watch it.
/delegate does not, which means the controls move from supervision to scope-and-review. Everything
the agents cluster says about delegation applies.
/fleet enables parallel subagent execution of parts of a task. Genuinely useful for work that
decomposes — analysing several services, applying the same change across modules — and it multiplies
the review surface proportionally.
Two cautions on parallel work:
Subagent output is less visible. What comes back is a summary. For anything consequential, check what was actually done rather than what was reported.
Parallel changes can conflict. Several agents editing a shared file produces exactly the merge problem the conflict lesson describes, with the added difficulty that nobody understood either side’s intent.
Scheduling exists too — /every for recurring prompts and /after for one-off delayed ones. Useful,
and worth the same scrutiny as any other automation that runs without you present.
Sandboxes
Section titled “Sandboxes”Copilot supports sandboxed execution, managed with /sandbox. Cloud and local sandboxes are in public
preview.
The value is straightforward: a sandbox bounds what a mistake can reach. An agent running in an isolated environment cannot touch your home directory, your credentials or your other repositories, which changes the calculus on how much to approve.
Where it fits: exploratory work, anything using --allow-all-tools, and unfamiliar plugins or MCP
servers. Where it does not: work that genuinely needs your local environment — a database running on
your machine, a service you have port-forwarded.
Plugins and marketplaces
Section titled “Plugins and marketplaces”Plugins bundle agents, skills, hooks and MCP or language-server configuration into an installable
package. A plugin directory contains, at minimum, a plugin.json manifest at its root naming the
plugin and pointing at what it provides.
{/* Install from a registered marketplace */}copilot plugin install NAMEMarketplaces are defined by a marketplace.json in a repository, which is the only required component —
adding it makes the repository installable from. Copilot ships with copilot-plugins and
awesome-copilot registered by default.
The trust question is the whole story here. A plugin can contain hooks — shell commands that run at lifecycle points — and MCP server configuration, which grants tools an agent can invoke. Installing one is closer to adding a dependency than to changing a setting.
Apply the same standard as dependency security:
Read what it contains before installing. copilot plugins list --json shows what a plugin provides
once installed; reading the repository shows it before.
Prefer known publishers, and be suspicious of a plugin with few users offering broad capability — the same signal that matters for packages.
Enterprise plugin standards exist precisely so this can be a policy decision rather than an individual one, which is the right answer for an organisation.
Context management
Section titled “Context management”The CLI exposes context management more directly than other surfaces, which is useful because context exhaustion is the most common cause of an agent getting worse mid-task.
/context shows the window’s usage and a visualisation of what is in it. Worth checking on any
session running longer than a few minutes.
/compact summarises the conversation to reclaim space, optionally with focus instructions telling
it what to preserve. That last part matters: an unfocused compaction may summarise away the constraint
you established early.
/clear starts fresh, and is frequently better than compacting. A new session with a tight goal and
two attached files outperforms a compacted session that has already drifted.
/ask asks a quick side question without adding to the conversation history, which is the right
tool for “what does this flag do” during a longer task — it does not spend context on a digression.
Subagents, via /fleet or automatic delegation, keep a large subtask’s reading out of the main
conversation entirely. Sending “read these forty files and report which handle auth” to a subagent
returns an answer without the forty files.
The signal that context is the problem: the agent re-reads files it has already read, asks about
something you established earlier, or produces vaguer output than it did twenty minutes ago. None of
these presents as an error, which is why /context is worth checking rather than inferring.
Working well
Section titled “Working well”-
Start in the right directory. Scope is the working directory plus anything you
/add-dir. -
Check what is loaded.
/envon a new repository, once. -
Use plan mode for anything non-trivial.
-
Grant narrow allowances up front.
--allow-tool='shell(git)'for Git work beats approving forty prompts. -
Watch
/contexton long sessions. Compact or start fresh rather than pushing through. -
Review the diff, not the transcript.
git diffafter the session, always. -
Branch first for anything that edits files.
What the CLI is good at
Section titled “What the CLI is good at”Being concrete about the fit, because “an agent in the terminal” is vague.
Anything where the context is command output. A failing build, a kubectl describe full of events,
a Terraform plan, a stack trace in a log file. The CLI reads them directly rather than you copying them
into a browser, and that fidelity difference is substantial.
Iterative diagnosis. Run, read the error, adjust, run again. The loop is the point, and it is painfully slow through a chat window.
Git work. The repository is right there, the commands are safe to read and dangerous to run, and the permission model maps onto that distinction precisely. See Copilot CLI for Git.
Reviewing your own changes. /review and /diff operate on your working tree without you
assembling anything, which removes the friction that makes people skip
self-review.
Multi-step operational tasks where each step’s output determines the next.
Where it is the wrong tool: anything you want a durable, reviewable record of — sessions are local and ephemeral, so that is a pull request. Anything requiring a graphical view of a diff. And anything you would not want happening while you looked away, which is delegation rather than an interactive session.
Using it in CI
Section titled “Using it in CI”The non-interactive form makes CI use possible, and it deserves a specific warning.
- name: Summarise the changes for the release notes run: | copilot -p "Summarise the commits in this range for release notes" \ --allow-tool='shell(git)' > notes.md env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}Three constraints that apply in CI and not interactively.
Nothing can prompt. Every permission must be granted up front, which means you must state exactly what the job needs. That is a feature — it forces the scope to be explicit and reviewable in the workflow file.
Never --allow-all-tools in CI. In an interactive session it is a bad idea you can interrupt. In
CI it is an unsupervised agent with the job’s credentials and no one watching. If a task seems to need
it, the task is wrong for CI.
Scope the credentials to the task. The job’s GITHUB_TOKEN permissions are the agent’s
permissions. Read-only unless there is a reason, following
least-privilege workflow permissions.
The tasks that suit CI are the ones producing text for a human to read — a release note draft, a summary of what changed, an analysis of a failure. Tasks that produce changes belong in a pull request from a delegated agent, where they get reviewed, rather than in a job that commits.
Common mistakes
Section titled “Common mistakes”--allow-all-tools on a repository that matters. It removes the control.
Running in a shell with production credentials. The agent inherits them.
Not checking /env. Configuration that is not loaded looks identical to configuration being
ignored.
Ignoring /context. A full window presents as the agent getting worse, not as an error.
/add-dir without thinking about scope. It grants file access and loads that directory’s agents
and skills.
Approving a command because the explanation was convincing. The explanation came from the same system.
Treating agent-run tests as CI. Local evidence, not the gate.
Using it to troubleshoot with broad permissions. The situation where you can least evaluate the commands is the one where they should be most scrutinised.
Reviewing a command before running it
Section titled “Reviewing a command before running it”The habit this whole cluster rests on, made concrete.
When the CLI proposes a command, four questions take about five seconds:
What does it actually do? Not what the explanation says — what the command does. If you cannot read it, that is the answer: ask what it does before approving.
What does it touch? Which files, which host, which cluster, which account. A command with a path is easier to evaluate than one with a glob.
Is it reversible? git status is free. git reset --hard is not. kubectl delete is not.
terraform apply is definitely not.
What would I do if it were wrong? If the answer is “I do not know”, do not run it yet.
Two patterns worth insisting on for anything consequential:
Ask for the read-only version first. terraform plan before apply, kubectl diff before
apply, --dry-run where it exists, git status before anything that changes state. A useful
instruction to give the agent directly:
Show me read-only commands to understand the situation first. Do not propose anything that changes state until I have shown you the output.
Make it explain destructive commands unprompted. A repository instruction along the lines of “for any command that deletes, force-pushes, or modifies infrastructure, state what it does and what would be lost before proposing it” changes the default behaviour usefully.
The framing that carries across this whole cluster: generating a command is research; running it is a decision. The CLI makes the first cheap, and it must not make the second automatic.
Configuration precedence and scope
Section titled “Configuration precedence and scope”Where configuration comes from, since the CLI reads more sources than any other surface.
Repository — .github/ in the working directory: instructions, skills, agents, hooks.
Directories added with /add-dir — their skills and agents are loaded too, which is the part
people miss.
Personal — ~/.copilot/, including personal instructions and skills in ~/.copilot/skills/ or
~/.agents/skills/. These follow you across projects.
Plugins — whatever they bundle, from wherever they were installed.
Organisation and enterprise — custom agents from an organisation’s .github or .github-private
repository. Note that organisation-level policies for MCP servers are not currently supported, which is
a real gap for anyone wanting to centrally restrict them.
Two practical consequences.
/env is the ground truth. With this many sources, reasoning about what should be loaded is less
reliable than asking.
Personal configuration can surprise colleagues. A skill in your home directory shapes your results and nobody else’s. When explaining a workflow to somebody, check whether it depends on something only you have — this is a common source of “it works for me”.
Mental model
Section titled “Mental model”Copilot CLI is an agent with your shell, your credentials and your repository, that asks before it acts. Everything about using it safely is deciding, in advance and while thinking clearly, what it should not have to ask about.
What you learned
Section titled “What you learned”copilotstarts an interactive session;-pruns a single prompt non-interactively- Non-interactive mode requires explicit allowances, which forces you to state what the task needs
- Narrow allowances like
--allow-tool='shell(git)'beat blanket approval /envshows what configuration is actually loaded;/contextshows window usage/add-dirgrants file access and loads that directory’s skills and agents- Plan mode makes the approach reviewable before any action
- The CLI reads
AGENTS.md,copilot-instructions.md,CLAUDE.md, skills, hooks, agents and MCP - It runs in your shell and inherits your environment and credentials
- Sandboxes bound what a mistake can reach, and are in public preview
Exercise
Section titled “Exercise”Use a disposable repository.
-
Start a session and run
/env. Predict: is anything loaded that you did not expect? -
Ask it to summarise recent commits. Predict: does it ask permission before running
git log? -
Restart with
--allow-tool='shell(git)'. Predict: which prompts disappear, and which remain? -
Ask for something requiring a non-Git command. Predict: does the allowance cover it?
-
Use
/planfor a multi-file change. Read the plan. Predict: would you have caught a wrong approach? -
Run a long session and watch
/context. Predict: at what point does output quality change? -
Add
.github/copilot-instructions.mdwith a specific rule and run/envagain. Predict: does it appear? -
Delete the repository.