Invoke Copilot CLI Sub-Session
Use this skill when a main session (in Copilot CLI or VS Code) needs to spawn a fresh, isolated Copilot CLI sub-session with full control over its identity and runtime.
When to use
- Run a long or risky sub-workflow in a separate process that does not pollute the main session context.
- Pin a specific custom agent to the sub-session.
- Pin a specific BYOK provider / model for the sub-session (default:
opencode-go-deepseek-v4-flash, reasoning-efforthigh; per-model levels are grounded in thecopilot-byokskill'sreferences/shared/reasoning-effort-lookup.md). - Self-generate a session name (
--name) and session UUID (--session-id) so the main session can send follow-up prompts to the same sub-session. - Capture structured output (text or JSONL) for programmatic parsing.
What it produces
- A PowerShell script:
scripts/Invoke-CopilotCliSubSession.ps1. - This skill guides the agent to call that script with the correct parameters. The agent should proactively assign a descriptive
-Namein kebab-case. - By default the sub-session inherits the main session's MCP servers and custom instructions (same working directory, same
~/.copilot/).
Quick start
# Minimal invocation — uses default BYOK profile (opencode-go-deepseek-v4-flash) at reasoning-effort high
.\scripts\Invoke-CopilotCliSubSession.ps1 `
-Name "analyze-async" `
-Prompt "Analyze the project structure and list all async methods."
# Specific agent, model override, named session, multi-line prompt
.\scripts\Invoke-CopilotCliSubSession.ps1 `
-Name "security-audit" `
-Agent "security-auditor" `
-Model "claude-opus-4.5" `
-SessionId "a1b2c3d4-e5f6-7890-abcd-ef1234567890" `
-Prompt @"
Review the codebase for security vulnerabilities:
1. Check for SQL injection in data access layer
2. Audit authentication middleware
3. Verify CSRF protection is active
4. Report findings with severity levels
"@
# Invoke a built-in command or skill via slash command
.\scripts\Invoke-CopilotCliSubSession.ps1 `
-SlashCommand "handoff" `
-Prompt "Describe the current session state" `
-Name "session-handoff"
# Invoke a skill without extra prompt
.\scripts\Invoke-CopilotCliSubSession.ps1 `
-SlashCommand "git-atomic-commit" `
-Name "auto-commit"
# Invoke with a custom agent
.\scripts\Invoke-CopilotCliSubSession.ps1 `
-Agent "dotnet-diag:optimizing-dotnet-performance" `
-Name "perf-analysis" `
-Prompt "Scan for async anti-patterns"
# Context handoff: list relevant file paths; sub-session reads them itself
.\scripts\Invoke-CopilotCliSubSession.ps1 `
-Name "exec-plan" `
-Prompt @"
Execute the implementation plan at:
c:/Workplace/my-repo/openspec/changes/auth-impl/plan.md
c:/Workplace/my-repo/openspec/changes/auth-impl/tasks.md
Reference specs:
c:/Workplace/my-repo/openspec/specs/auth/spec.md
Working directory: c:/Workplace/my-repo
Read each file before executing. Report progress after each step.
"@
# Chain two prompts on the same sub-session by reusing SessionId
$uuid = "b2c3d4e5-f6a7-8901-bcde-f12345678901"
$r1 = .\scripts\Invoke-CopilotCliSubSession.ps1 `
-Name "research-auth" `
-SessionId $uuid `
-Prompt "Research this repo's authentication approach." `
-JsonOutput
$r2 = .\scripts\Invoke-CopilotCliSubSession.ps1 `
-Name "research-auth" `
-SessionId $uuid `
-Prompt "Based on the research, propose three security improvements." `
-JsonOutput
Required vs optional parameters
| Parameter | Required | Default | Purpose |
|---|---|---|---|
-SlashCommand |
No | — | Built-in command or skill name to invoke (e.g., handoff, git-atomic-commit, plan, review). Script prepends /. When given with -Prompt, the prompt becomes the command argument. At least one of -SlashCommand or -Prompt is required. |
-Prompt |
No* | — | The task prompt, or argument to -SlashCommand when both are given. Supports multi-line (here-strings, `n, literal newlines). *Required when -SlashCommand is not provided. |
-Name |
No | — | Human-readable session name (--name). Use kebab-case slugs (e.g. "analyze-async"). The agent should proactively generate one. |
-SessionId |
No | auto-generated UUID | Custom UUID for --session-id. Must be valid UUID format. When omitted, a UUID is auto-generated. Reuse the same value across calls to chain messages on the same session. |
-Agent |
No | — | Custom agent name. Qualify plugin agents as plugin:agent-name (colon, e.g. dotnet-diag:optimizing-dotnet-performance). Repo agents use bare name. |
-Model |
No | — | Model override. Takes precedence over the BYOK profile's model. |
-ByokProfile |
No | opencode-go-deepseek-v4-flash |
BYOK profile name from ~/.copilot/byok-profiles.json. |
-ByokAccount |
No | — | Account override for account-grouped profiles (e.g., multiple OpenCode Go subscriptions). Takes precedence over the profile's account pin and the config-level activeAccount. When omitted, the profile pin or activeAccount is used. |
-CopilotHome |
No | — | Staging COPILOT_HOME for the sub-process — the explicit opt-in to full config isolation (CLI 1.0.77+: --config-dir was removed; COPILOT_HOME is the supported override). The first time this path is used, the script seeds a minimal staging tree from production ~/.copilot: byok-profiles.json (required) plus mcp-config.json when present. Seeding runs once only — afterwards production and staging are fully independent; staging is durable and never re-seeded or auto-cleaned (delete the tree manually to reset). Default: production ~/.copilot (no isolation). Alias: -ConfigDir (deprecated). |
-ReasoningEffort |
No | high |
none, minimal, low, medium, high, xhigh, max (per-model subset may vary; minimal is newer — verified in CLI 1.0.77). The default BYOK profile (opencode-go-deepseek-v4-flash) runs at high by default. For the grounded per-model lookup — which levels a model supports and whether to omit the flag — see the copilot-byok skill's references/shared/reasoning-effort-lookup.md. |
-WorkingDir |
No | current location | Working directory for the sub-process. |
-JsonOutput |
Switch | off | Emit JSONL instead of plain text. |
-NoAllowAll |
Switch | off | Opt out of --allow-all --no-ask-user. By default the sub-session runs with full permissions. |
-DisableBuiltInMcps |
Switch | off | Isolate from main session's MCP servers. |
-NoCustomInstructions |
Switch | off | Skip project custom instructions. |
-TimeoutSeconds |
No | 600 |
Kill the sub-process after N seconds. |
-Passthrough |
No | — | Extra arguments forwarded to copilot. |
Session naming (-Name)
The agent should always assign a meaningful -Name in kebab-case that describes the sub-session's purpose:
"research-csrf-patterns"— a research task"implement-oauth-middleware"— an implementation task"review-pr-142"— a review task
This name appears in copilot --resume listings and session logs. It is distinct from -SessionId (the UUID used for programmatic chaining). Pass both: -Name for human readability, -SessionId for script-level chaining.
Choosing a session ID
- Auto-generated: when
-SessionIdis omitted, a valid UUID is auto-generated usingNew-Guid. Every call gets a fresh session unless you reuse the same UUID. - Explicit UUID: pass a valid UUID (
xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx). Invalid UUIDs trigger a warning and are replaced with an auto-generated one. - Follow-up to the same sub-session: reuse the exact same
-SessionIdvalue; the prior session state is reloaded via--session-id. - Valid UUIDs only:
--session-idrequires standard format (xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx).
Multi-line prompts
-Prompt accepts multi-line strings natively. Use PowerShell here-strings for multi-paragraph task descriptions:
.\scripts\Invoke-CopilotCliSubSession.ps1 `
-Name "code-review" `
-Prompt @"
Review the following PR checklist:
1. Verify all edge cases are covered
2. Check for proper error handling
3. Ensure tests pass with >80% coverage
4. Validate API contract changes
Report findings in a markdown table.
"@
Inline newlines via `n also work: -Prompt "Line 1nLine 2nLine 3".
Slash command invocation (-SlashCommand)
-SlashCommand wraps Copilot CLI's interactive slash commands for non-interactive use. Pass just the command name (no leading /) — the script prepends / automatically.
Supported commands: Any built-in CLI command (help, init, diff, pr, review, plan, research, delegate, rewind, compact, share, allow-all, add-dir, skills) and any installed skill (git-atomic-commit, handoff, mermaid-creator, etc.).
⚠️
modelis excluded from reliable non-interactive use (verified CLI 1.0.77, 2026-08-03, BYOK/custom-provider routing).-p "/model X"forwards the text to the current model as a prompt — it roleplays the switch and the backend never changes (model.call_startstays the same in JSONL). ⚠️ Scope of this finding: the roleplay behavior was verified with BYOK (custom provider, e.g. OpenCode Go). For GitHub Copilot Subscription models it is unverified — do not assume-p "/model X"is roleplay there, since model selection routes through the GitHub platform rather than a custom endpoint. The only verified in-session switch is the interactive TUI/modelpicker (emitssession.model_change); the only verified programmatic switch is-Model/--modelat process start (e.g.-Model kimi-k2.7-code), which switches the real backend.
# Slash command only
.\scripts\Invoke-CopilotCliSubSession.ps1 -SlashCommand "plan" -Name "planning-pass"
# Slash command with arguments (Prompt becomes the argument)
.\scripts\Invoke-CopilotCliSubSession.ps1 -SlashCommand "handoff" -Prompt "Describe session results" -Name "handoff-pass"
# Equivalent freeform prompt (also valid)
.\scripts\Invoke-CopilotCliSubSession.ps1 -Prompt "/handoff Describe session results" -Name "handoff-pass"
Multi-step orchestration pattern:
# Plan → Execute → Review with slash commands
.\scripts\Invoke-CopilotCliSubSession.ps1 -SlashCommand "plan" -Prompt "Implement user auth" -Name "plan-auth" -SessionId $uuid
.\scripts\Invoke-CopilotCliSubSession.ps1 -Prompt "Execute the plan above" -Name "exec-auth" -SessionId $uuid
.\scripts\Invoke-CopilotCliSubSession.ps1 -SlashCommand "review" -Name "review-auth" -SessionId $uuid
Custom agent invocation (-Agent)
Pin a specific agent to the sub-session. Plugin agents use colon: plugin:agent-name. Repo agents use bare name.
# Plugin agent
.\scripts\Invoke-CopilotCliSubSession.ps1 `
-Agent "dotnet-diag:optimizing-dotnet-performance" `
-Prompt "Analyze this project's performance" `
-Name "perf-analysis"
# Repo agent (discovered from .github/agents/)
.\scripts\Invoke-CopilotCliSubSession.ps1 `
-Agent "my-custom-agent" `
-Prompt "Execute the workflow" `
-Name "custom-workflow"
Agent discovery paths (in precedence order):
~/.copilot/agents/(user-level).github/agents/(repo-level)plugin:agent-name(qualified, from installed plugins)
The agent is invoked via the Copilot CLI --agent flag and inherits the sub-session's model, BYOK config, and all other parameters.
Context handoff convention
When delegating to a sub-session, always prioritize listing the full absolute paths of relevant files in -Prompt. The sub-session can read those files itself using its own tools (cat, grep, read). Only embed content inline when the context is short and simple enough to fit in a single message.
Why
- The sub-session starts with a blank context — it does not know what files the main session worked with, what decisions were made, or what artifacts exist.
- MCP and custom instructions inheritance provides environment (tools, config), not session memory.
- Listing file paths is cheaper, avoids duplication, and lets the sub-session choose what to read in depth.
Do this
# PREFERRED — list full paths; sub-session reads files itself
.\scripts\Invoke-CopilotCliSubSession.ps1 `
-Name "exec" `
-Prompt @"
Execute the implementation plan at:
c:/Workplace/my-repo/openspec/changes/auth-impl/plan.md
c:/Workplace/my-repo/openspec/changes/auth-impl/tasks.md
Reference specs:
c:/Workplace/my-repo/openspec/specs/auth/spec.md
Start from working directory: c:/Workplace/my-repo
After each step, report progress.
"@
# EXCEPTION — directly embed only when context is short and simple
.\scripts\Invoke-CopilotCliSubSession.ps1 `
-Name "quick-fix" `
-Prompt "Fix the typo in src/utils/helpers.ts line 42: change 'teh' to 'the'."
Practical workflow
- Identify the relevant files from the main session (plan, research, spec, ADR, design doc, task list).
- List their full absolute paths in the
-Promptargument, grouped by role. - Include the working directory and the final instruction — what the sub-session should produce.
- Only embed content inline (via here-string) when the context is trivially short (a few lines).
- Use the returned
SessionIdto chain follow-up messages if the task requires multiple turns.
What to reference
| Context type | Files to reference by path |
|---|---|
| Implementation plan | openspec/changes/*/plan.md, openspec/changes/*/tasks.md |
| Research findings | openspec/research/*.md, docs/design-docs/*.md |
| Specifications | openspec/specs/**/spec.md, requirements/*.md |
| Active task checklist | Current todo list, task breakdown |
| Configuration / conventions | .github/git-scope-constitution.md, relevant *.agent.md |
| Copilot CLI session state | ~/.copilot/session-state/<session-uuid>/ (see below) |
Copilot CLI session-state handoff
When the main session is itself a Copilot CLI session, its session state is persisted under ~/.copilot/session-state/<session-uuid>/. These files capture what the main session already worked on — plans, research, file changes, and checkpoints. Forward them to the sub-session so it does not start from scratch.
| File / Dir | Description |
|---|---|
plan.md |
The implementation plan generated by /plan. The sub-session should read this to understand what to build and in what order. |
research/ |
Output from /research. Contains search results, analyzed code snippets, and external references the main session already gathered. |
files/ |
File snapshots or diffs touched during the session. Lets the sub-session see what was changed without re-reading the whole repo. |
checkpoints/ |
Session checkpoints. Useful for resuming work from a specific point if the sub-session needs to continue where the main session left off. |
How to discover the session UUID:
# List all session IDs
Get-ChildItem "$HOME\.copilot\session-state" -Directory | Select-Object Name
# Or get the latest session
Get-ChildItem "$HOME\.copilot\session-state" -Directory |
Sort-Object LastWriteTime -Descending |
Select-Object -First 1 -ExpandProperty Name
How to reference in -Prompt:
# PREFERRED — pass knowledge from previous session
.\scripts\Invoke-CopilotCliSubSession.ps1 `
-Name "continue-from-session" `
-Prompt @"
Continue the work from the previous Copilot CLI session.
Session state is at:
~/.copilot/session-state/a1b2c3d4-e5f6-7890-abcd-ef1234567890/
Review these files before executing:
~/.copilot/session-state/a1b2c3d4-e5f6-7890-abcd-ef1234567890/plan.md
~/.copilot/session-state/a1b2c3d4-e5f6-7890-abcd-ef1234567890/research/
~/.copilot/session-state/a1b2c3d4-e5f6-7890-abcd-ef1234567890/files/
Working directory: c:/Workplace/my-repo
Continue from where the plan left off.
"@
Note: The session-state directory is tied to the main session's UUID. The sub-session gets its own separate session-state (under its own --session-id). Forwarding the main session's state paths is what bridges the gap.
Path formatting
- Use absolute paths (
c:/Workplace/my-repo/...) so the sub-session can read them regardless of its working directory. - If the sub-session's
-WorkingDirmatches the repo root, relative paths rooted there also work. - Group paths by purpose with a short header line before each group.
MCP and custom instructions inheritance
By default the sub-session inherits the main session's MCP servers and custom instructions because:
- It runs in the same working directory (project-level
.mcp.json,.github/mcp.json,copilot-instructions.mdare picked up). - It uses the same
~/.copilot/directory (user-levelmcp-config.json, agents, skills).
To isolate the sub-session, pass -DisableBuiltInMcps and/or -NoCustomInstructions. To fully isolate, set -CopilotHome (mapped to $env:COPILOT_HOME for the sub-process) to a separate config tree.
Staging COPILOT_HOME — the skill's testing sandbox (dojo)
-CopilotHome <path> is the explicit opt-in to a staging COPILOT_HOME — a durable, separate config tree that keeps test sub-sessions from polluting the production ~/.copilot/. The recommended convention is a sibling directory, e.g. Join-Path $HOME '.copilot-dojo' (derived from $HOME, so it works on any machine — never hardcode a user path).
Why a staging env (dojo vision): staging is the designated testing environment for this skill and its ecosystem. Any sub-session spawned with -CopilotHome runs fully inside staging — session state, checkpoints, logs, BYOK profile, and MCP config all land there — so you can exercise every supported feature of this skill (custom agents, slash commands, model pinning/switching, session chaining, BYOK profiles, MCP/custom-instructions isolation, reasoning-effort handling) without touching production. Because env vars are process-scoped, the main (root) session keeps running in production ~/.copilot/ while the child works in staging (verified: parent env is never modified).
Tight feedback loop (develop the skill safely):
- Edit the artifact under test — e.g.
scripts/Invoke-CopilotCliSubSession.ps1, thisSKILL.md, or a referenced skill/agent. - Stage it — repo-level skills/agents/hooks are picked up from the working directory (
.github/skills/,.github/agents/,.github/hooks/) with no extra step (discovery is workspace-relative, independent ofCOPILOT_HOME). Personal-level artifacts can be staged with the publish scripts'-CopilotHomeoverride:# Agents → <CopilotHome>/agents (skips WSL mirroring) pwsh -NoProfile -File scripts/publish/publish-agents.ps1 -CopilotHome "$HOME\.copilot-dojo" -Force # Instructions → <CopilotHome>\Code\{Stable|Insiders}\User\prompts (skips WSL) pwsh -NoProfile -File scripts/publish/publish-instructions.ps1 -CopilotHome "$HOME\.copilot-dojo" -Force # User-level hooks → <CopilotHome>/hooks (skips WSL + VS Code settings mutation) pwsh -NoProfile -File scripts/publish/publish-hooks.ps1 -Scope user-level -CopilotHome "$HOME\.copilot-dojo" -Force # Or direct copy for anything else Copy-Item -Recurse "$PWD\skills\copilot-cli-subsession" "$HOME\.copilot-dojo\skills\" - Spawn a sub-session in staging:
.\scripts\Invoke-CopilotCliSubSession.ps1 -CopilotHome "$HOME\.copilot-dojo" -Prompt "test the change" - Observe — the returned object's
CopilotHomeconfirms the child used staging; session artifacts live under$HOME\.copilot-dojo\session-state\<session-uuid>\. - Iterate — repeat 1–4. Staging is never re-seeded and never auto-cleaned, so state persists across iterations; delete the tree to reset.
Seeding & independence:
- One-time seeding: the first time the staging path is used (its
byok-profiles.jsonis missing), the script seeds a minimal functional tree from production —byok-profiles.json(required) plusmcp-config.jsonwhen present. This makes an empty staging dir immediately usable. - Independent envs: after seeding, production and staging are fully independent. The staging tree is never re-seeded (existing files are never overwritten) and never auto-cleaned — the user owns its lifecycle. Delete the tree to reset.
- What's available in staging: always the seeded
byok-profiles.json+mcp-config.json, plus repo-level agents/skills/hooks from the working directory; personal-level agents/skills/hooks andmoonshot-proxyonly if staged in (publish scripts accept-CopilotHome, or copy manually). - Profile resolution: with
-CopilotHome, the BYOK profile is resolved from the staging tree (seeded copy). Production'sbyok-profiles.jsonis the seed source, not a live fallback — the staged copy is authoritative. - Chaining in staging: to resume a staging sub-session, pass the same
-CopilotHomeplus the same-SessionId— session state lives under staging, not production.
BYOK profile handling
The script looks up the profile in ~/.copilot/byok-profiles.json (production) or, when -CopilotHome is given, the seeded staging tree ($env:COPILOT_HOME/byok-profiles.json). The default profile is opencode-go-deepseek-v4-flash.
It maps profile fields to environment variables:
COPILOT_PROVIDER_BASE_URL
COPILOT_PROVIDER_TYPE
COPILOT_MODEL
COPILOT_PROVIDER_API_KEY
COPILOT_PROVIDER_WIRE_API
COPILOT_PROVIDER_MAX_PROMPT_TOKENS
COPILOT_PROVIDER_MAX_OUTPUT_TOKENS
COPILOT_OFFLINE
If the profile contains proxyPort, the script routes the request through the local Moonshot proxy (https://moonshot.local/v1) used by copilot-byok.
A -Model parameter, when provided, takes precedence over the profile's model.
Switching models within a sub-session
Verified CLI 1.0.77 (2026-08-03): -p "/model X" does not switch the backend model (the current model roleplays the switch) — verified under BYOK/custom-provider routing only. ⚠️ Do not generalize to GitHub Copilot Subscription models: there the CLI selects models via the GitHub platform (not a custom endpoint), and -p "/model X" behavior is unverified — treat it as unreliable and prefer the interactive TUI /model picker, which is the verified in-session switch (it emits session.model_change and subsequent calls route to the new model). The verified programmatic switch is -Model / --model at process start. For OpenCode Go, all models (DeepSeek, GLM, Kimi, MiMo, Qwen3.x, MiniMax, GPT-5.6 Luna) are served through the single OpenAI chat/completions endpoint — the anthropic type and Responses-only constraints documented earlier were falsified by probe (see copilot-byok references/provider/opencode-go/cli.md and references/shared/environment-variables.md).
Reasoning effort per model
The script forwards --reasoning-effort (default high) only when the resolved profile supports it. If the profile carries "reasoningEffortSupported": false (models whose API exposes no controllable levels — e.g., Kimi K2.x, GLM, MiMo, Qwen3.x, MiniMax), the argument is stripped with a warning, mirroring byok-profile.ps1 run. The authoritative per-model lookup — which levels a model supports and the recommended default — is the copilot-byok skill's references/shared/reasoning-effort-lookup.md. For the default profile (deepseek-v4-flash), high is within the supported low/medium/high range.
Copilot SDK parity & keeping up
The CLI flag surface, COPILOT_* env vars, the .NET SDK (copilot-sdk-dotnet), and VS Code chatLanguageModels.json are four façades over the same Copilot CLI engine. The single source of truth for how they map is the capability parity matrix — update it whenever a new capability appears in any surface, and link it from new reference material instead of re-documenting equivalence.
To detect drift between this skill's documented surface and the installed CLI, run the parity gate before publishing:
.\scripts\Test-CopilotCliParity.ps1
The gate compares documented flags, env vars, and reasoning-effort levels against copilot --help / copilot help environment, exits non-zero on drift, and lists new capabilities the CLI gained that the skill does not document yet. After re-verifying, bump lastVerified / verifiedCliVersion in this skill's frontmatter and the Verified column of the matrix.
Historical (v1.0.77, resolved 2026-08-03): --config-dir is no longer listed in CLI help; -CopilotHome maps to COPILOT_HOME for the sub-process (the supported config-override mechanism). The parameter was originally named -ConfigDir (deprecated alias retained).
Output
By default the script returns a plain-text block. With -JsonOutput it returns JSONL; the final result line contains exitCode and usage.
The script prints a structured result object (metadata only — StdOut is written to the console directly):
[PSCustomObject]@{
ExitCode = $proc.ExitCode
SlashCommand = $SlashCommand
Name = $Name
SessionId = $SessionId
Agent = $Agent
Model = $env:COPILOT_MODEL
ByokProfile = $ByokProfile
}
Safety rules
- Always assign a descriptive
-Namein kebab-case. -NoAllowAlllets you opt out of the default--allow-all --no-ask-userfor read-only or untrusted contexts.- The sub-session inherits MCP and custom instructions by default; use
-DisableBuiltInMcpsor-NoCustomInstructionsonly when isolation is intended. - The sub-process inherits the main session's environment except where the script overrides it.
Tests (empirical argument audit)
Terminology used here (shim, live mode, KNOWN-GAP, polarity-agnostic, case-ID buckets, dojo, COST GUARDRAIL) is defined in the harness vocabulary glossary — self-contained within this skill, so it travels with the skill when published.
tests/Invoke-CopilotCliSubSession-args-audit.ps1 is an empirical audit harness that executes the real
script against the seeded staging home (~/.copilot-dojo, the "dojo") and asserts, for every supported
argument: the exact CLI argv forwarded to the copilot child (via a shim), the COPILOT_* env emitted, the
9-field return object, and seeding/validation/precedence behaviors. It includes an opt-in live pass
(-Live, cheap models only, COST GUARDRAIL enforced) that probes real sub-sessions: session-state
events.jsonl, model.call_start, slash command, custom agent, SessionId chaining, and same/different-family
model hot-switching and cold-switch resume (l8: luna→flash across an exit+resume).
# Shim matrix (zero cost, deterministic)
pwsh -NoProfile -File skills/copilot-cli-subsession/tests/Invoke-CopilotCliSubSession-args-audit.ps1
# Shim matrix + live probes (real keys; needs OPENCODE_API_KEY_WORK in this process)
pwsh -NoProfile -File skills/copilot-cli-subsession/tests/Invoke-CopilotCliSubSession-args-audit.ps1 -Live
# Dispatcher equivalents
pwsh -NoProfile -File scripts/workspace/run-command.ps1 -Command tests:subsession-audit
pwsh -NoProfile -File scripts/workspace/run-command.ps1 -Command tests:subsession-audit-live
Exit codes: 0 all passed, 1 any failed, 2 harness/preflight error. Known-gap locks (s4-3, s5-4, s9-4,
s11-2, l2, ...) report as PASS with a gap label so the harness stays green while documenting behavior.
Reports land in scripts/test/.artifacts/copilot-cli-subsession-args-audit/run-<ts>-<pid>/report.md.
Evolve cases in tests/ and re-run on demand; the fixture (tests/fixtures/byok-profiles.fixture.json)
drives throwaway-home cases so production and the dojo are never mutated (verified by isolation gates).