Copilot CLI is a unix app
So far most patterns i have seen with Github copilot CLI is either interactive or headless in CI, but it is not the only way, and honestly, for a lot of my use case, it is what i do with it. I am all over the place doing X and Y simultaneously, and I just want to ask a quick question about X without leaving my terminal or context. Or I want to pipe some data into it, get an answer, and pipe that into another command. That is the Unix way. And with the right flags, Copilot CLI can fit right into that pattern.
The copilot CLI has a headless mode. No chat UI. No prompts waiting for input. You fire a question at it, you get an answer back, and it exits. That makes it work exactly like any other Unix tool. Pipe data in. Pipe output out. Embed it in scripts. Use it in CI. Compose it with grep, awk, jq, or whatever else you already have.
I will try to cover some of my patterns. I must apologize to Windows folks, I am not a Windows user, but I am sure there are similar patterns you can do with PowerShell, and I hope that inspires you.
The flags that matter
But first, the flags. Copilot CLI has several flags that unlock headless use. These are the ones I actually care about:
-p "prompt" runs a single prompt and exits. This is the core of everything. Without it, you get the interactive chat UI.
--silent outputs only the agent response (no stats). This is what makes piping work cleanly.
--no-ask-user makes the CLI never pause waiting for your input. Important for scripts where nobody is watching.
--no-color turns off color output. No ANSI codes means the output pipes cleanly without junk characters.
--disable-builtin-mcps skips loading MCP servers on startup. This is mostly a speed thing. Cold start is noticeably faster without it. And maybe you want that, but more on that later.
There are also a lot more interesting flags, and depending on your use case you might want to explore them, especially around tool permissions. But let’s skip that for now and focus on the core pattern of using Copilot as a Unix tool.
The two shell functions I use every day
Instead of typing the full command every time, I keep two small shell functions in my .bashrc. They take care of the boring parts: reading stdin if something is piped in, combining it with your inline arguments, and calling copilot with the right flags.
So I abbreviate them to ca (Copilot Ask) and cap (Copilot Ask Premium).
# extract_code is a helper function that takes copilot's full output and extracts the code blocks.
extract_code() {
local buf
buf=$(cat)
if printf '%s\n' "$buf" | grep -q '^[[:space:]]*```'; then
printf '%s\n' "$buf" | sed -n '/^[[:space:]]*```/,/^[[:space:]]*```/{
/^[[:space:]]*```/d
/^[[:space:]]*[-*]/d
/^[Nn]ote:/d
/^[[:space:]]*$/d
p
}'
else
printf '%s\n' "$buf"
fi
}
# ca: lightweight, fast model, good for quick questions, and uses 0x premium tokens
ca() {
local stdin_text args_text cp_prompt sep
args_text="$*"
if [[ -t 0 ]]; then
stdin_text=""
else
stdin_text="$(cat)"
fi
if [[ -n "$stdin_text" && -n "$args_text" ]]; then
sep=$'\n----\n'
cp_prompt="${stdin_text}${sep}${args_text}"
elif [[ -n "$stdin_text" ]]; then
cp_prompt="$stdin_text"
else
cp_prompt="$args_text"
fi
copilot --disable-builtin-mcps --allow-all-urls --silent --no-ask-user --model gpt-5-mini -p "$cp_prompt" | extract_code
}
# cap: with claude-sonnet-4.6
cap() {
local stdin_text args_text cp_prompt sep
args_text="$*"
if [[ -t 0 ]]; then
stdin_text=""
else
stdin_text="$(cat)"
fi
if [[ -n "$stdin_text" && -n "$args_text" ]]; then
sep=$'\n----\n'
cp_prompt="${stdin_text}${sep}${args_text}"
elif [[ -n "$stdin_text" ]]; then
cp_prompt="$stdin_text"
else
cp_prompt="$args_text"
fi
copilot --disable-builtin-mcps --allow-all-urls --no-ask-user --silent --model claude-sonnet-4.6 -p "$cp_prompt" | extract_code
}
The key piece is [[ -t 0 ]]. This checks whether stdin is a terminal. If it is, nothing is being piped in, so $stdin_text stays empty. If it is not a terminal, something is being piped in, and we read it with ca.
When you have both piped content and inline arguments, the function combines them with a separator line ’----’ and sends the whole thing as one prompt. This way you can pipe a file in and add instructions as arguments, and Copilot sees both clearly.
ca uses gpt-4o-mini: fast, cheap, good enough for most questions. cap uses claude-sonnet-4.6. I reach for cap when I need actual code changes or deeper reasoning.
What this looks like in practice
Ask a quick question without typing into a chat window:
ca "what does SIGTERM do?"
Pipe an error log in and ask what is wrong:
cat error.log | ca "what's wrong here?"
Pipe a file and add instructions as arguments:
cat Makefile | ca "why is my clean not remove the build directory?"
Chain the output into another command. This one is fun:
# pretty stupid example but to show the pattern.
cat > file.txt << 'EOF'
some asd sadas d 1.1.1.1,8.8.8.8, not an IP 1.1
asdd 2.2.2.2 asdas more text asdasdas asdad 1.1.1.1
8.8.8.8
EOF
ca "write a one liner bash to grep for unique IPs in 'file.txt', no explanation needed." > unique.txt
Summarize your staged diff before writing a commit message:
git diff --staged | ca "summarize these changes per file"
Understand a man page without reading the whole thing lazy Adham:
man curl | ca "give me the 5 most useful curl flags"
# or
man curl | ca "how do I measure time to first byte ?"
For heavier tasks, use cap:
cat src/server.go | cap "refactor error handling to use structured logging" > src/server.go
Each of these follows the same Unix pattern. Data goes in, something processes it, output comes out. Copilot just happens to be the processor.
Tool permissions
When Copilot is allowed to take actions, not just answer questions, you control exactly what it can do with --allow-tool and --deny-tool.
| Flag | What it does |
|---|---|
--allow-tool='shell(git:*)' | Allow only git subcommands |
--allow-tool='write' | Allow file writes |
--deny-tool='shell(rm)' | Block the rm command |
--allow-all-tools | Allow everything |
--yolo | Alias for allow-all, no confirmation prompts |
For scripting, the safe move is to allow only what you actually need. For a script that should read files and run git commands but nothing else:
copilot --allow-tool='shell(git:*), read' --deny-tool='shell(rm)' --silent -p "$prompt"
--yolo or --allow-all-tools is fine for “isolated environment” experimentation where you trust what you are running, but I would not use it in CI or on production systems without thinking about it first.
Summary
Copilot CLI becomes a full Unix tool the moment you add -p, --silent, and --no-ask-user. It reads input, returns output, and exits. No chat window, no interactive prompts, just data in and data out.
Two shell wrappers make this practical. ca for quick questions with a fast and cheap model. cap for code changes and deeper reasoning with a more capable model. Both handle piped input automatically and combine it with your inline arguments.
The patterns are simple: ask questions, pipe logs or configs in, summarize git diffs, or run refactors and redirect the output. When you need Copilot to take actions beyond answering, --allow-tool and --deny-tool let you control exactly what it can touch.
If you already think in pipelines, Copilot CLI is just another tool in the chain.
References
- GitHub Copilot CLI documentation covers the CLI flags and programmatic usage options
- GitHub Copilot CLI command reference has the full list of flags including
--allow-tool,--deny-tool, and model options