Summary
When launching with copilot --config-dir <alt>, the core skill loader correctly reads <alt>/settings.json — the <available_skills> block in the session's system prompt matches the alt settings. However, the interactive /skills slash-command UI appears to read ~/.copilot/settings.json via a hardcoded path, so the "checked/unchecked" state it displays does not reflect the active session's effective configuration when --config-dir is used.
Version / environment
GitHub Copilot CLI 1.0.35-6
- macOS Darwin 25.4.0 arm64
Impact
Two surfaces of the same setting disagree within one session:
- Loader (authoritative, drives what the model can invoke): respects
--config-dir.
/skills UI: ignores --config-dir.
This breaks workflows that use --config-dir for per-session skill/plugin overrides (e.g. ephemeral wrapper scripts that copy the real config dir to a temp location, mutate settings.json, and launch). The skill is genuinely on/off as intended, but the user's primary visibility tool (/skills) doesn't reflect it.
Reproduction
# 1. Pick any user skill currently enabled (not in disabledSkills), e.g. skill-builder.
# Assume ~/.copilot/settings.json has disabledSkills = [].
# 2. Build an alt config dir with skill-builder disabled.
ALT=$(mktemp -d)
for e in ~/.copilot/*; do
b=$(basename "$e")
[[ $b == config.json || $b == settings.json ]] && continue
ln -s "$e" "$ALT/$b"
done
sed 's|^[[:space:]]*//.*$||' ~/.copilot/config.json | jq . > "$ALT/config.json"
jq '.disabledSkills = ["skill-builder"]' ~/.copilot/settings.json > "$ALT/settings.json"
# 3. Non-interactive check — loader respects alt:
copilot --config-dir "$ALT" -p "List skill names in your <available_skills>."
# → skill-builder is ABSENT ✅
# 4. Interactive check — /skills UI does NOT respect alt:
copilot --config-dir "$ALT"
# > /skills
# → skill-builder is shown as CHECKED ❌ (expected: unchecked)
Additional evidence
- After step 4,
stat on $ALT/settings.json shows mtime unchanged since creation — /skills neither wrote through to it nor invalidated it.
~/.copilot/settings.json mtime is also unchanged — so /skills reads it but doesn't need to write on a pure view.
- In an earlier test where
settings.json in the alt dir was a symlink back to the real file, toggling /skills inside a --config-dir session leaked the change straight into ~/.copilot/settings.json. Further suggests the UI path is resolved against $HOME rather than the config-dir argument.
Expected
/skills UI should read (and write) <config-dir>/settings.json when --config-dir is passed, consistent with the loader and with how other config files under the dir are handled. Same likely applies to /plugin and /model views if they share this code path.
Workaround
None external to the CLI. A wrapper can make --config-dir affect actual skill-availability behavior, but cannot make /skills UI agree with it.
Summary
When launching with
copilot --config-dir <alt>, the core skill loader correctly reads<alt>/settings.json— the<available_skills>block in the session's system prompt matches the alt settings. However, the interactive/skillsslash-command UI appears to read~/.copilot/settings.jsonvia a hardcoded path, so the "checked/unchecked" state it displays does not reflect the active session's effective configuration when--config-diris used.Version / environment
GitHub Copilot CLI 1.0.35-6Impact
Two surfaces of the same setting disagree within one session:
--config-dir./skillsUI: ignores--config-dir.This breaks workflows that use
--config-dirfor per-session skill/plugin overrides (e.g. ephemeral wrapper scripts that copy the real config dir to a temp location, mutatesettings.json, and launch). The skill is genuinely on/off as intended, but the user's primary visibility tool (/skills) doesn't reflect it.Reproduction
Additional evidence
staton$ALT/settings.jsonshows mtime unchanged since creation —/skillsneither wrote through to it nor invalidated it.~/.copilot/settings.jsonmtime is also unchanged — so/skillsreads it but doesn't need to write on a pure view.settings.jsonin the alt dir was a symlink back to the real file, toggling/skillsinside a--config-dirsession leaked the change straight into~/.copilot/settings.json. Further suggests the UI path is resolved against$HOMErather than the config-dir argument.Expected
/skillsUI should read (and write)<config-dir>/settings.jsonwhen--config-diris passed, consistent with the loader and with how other config files under the dir are handled. Same likely applies to/pluginand/modelviews if they share this code path.Workaround
None external to the CLI. A wrapper can make
--config-diraffect actual skill-availability behavior, but cannot make/skillsUI agree with it.