Support skill filtering for project-local skills.config entries
What version of Codex is running?
codex-cli 0.125.0
Which platform / environment?
macOS, Codex CLI installed via npm (@openai/codex).
What happened?
Project-local .codex/config.toml is loaded for normal project configuration, but [[skills.config]] entries in that project config do not affect the model-visible skills list.
This makes it impossible to selectively disable globally installed skills for one repository while keeping them available in other repositories.
For example, this project-local config does not hide codebase-to-course:
# <repo>/.codex/config.toml
[[skills.config]]
name = "codebase-to-course"
enabled = false
Nor does the path selector variant:
# <repo>/.codex/config.toml
[[skills.config]]
path = "/Users/me/.codex/skills/codebase-to-course/SKILL.md"
enabled = false
Running:
codex debug prompt-input 'test skill visibility' | rg 'codebase-to-course'
still shows the skill in <skills_instructions>.
However, the same setting does work when provided from the user config or from session flags:
codex debug prompt-input \
-c 'skills.config=[{name="codebase-to-course", enabled=false}]' \
'test skill visibility' | rg 'codebase-to-course'
In that case, the skill is absent from the generated prompt input.
Expected behavior
For a trusted project, [[skills.config]] in <repo>/.codex/config.toml should be able to enable or disable specific skills for that project only, using the same selectors that work in ~/.codex/config.toml and -c.
This would allow a common workflow:
- Keep useful skills globally installed and available by default.
- Disable unrelated/heavy skills in specific repositories.
- Avoid disabling those skills globally for all other projects.
Actual behavior
Project-local [[skills.config]] entries are ignored for skill filtering. Globally installed skills remain visible in that project.
As a partial workaround, this project-local config does work:
[skills]
include_instructions = false
but that disables the entire skill instruction block, rather than selectively disabling a few skills.
Possible cause
From a quick source read, project config itself appears to be loaded, and project-local skills are also treated as skill roots.
But skill_config_rules_from_stack() currently only reads skills.config rules from ConfigLayerSource::User and ConfigLayerSource::SessionFlags, skipping ConfigLayerSource::Project:
if !matches!(
layer.name,
ConfigLayerSource::User { .. } | ConfigLayerSource::SessionFlags
) {
continue;
}
This seems to explain the behavior:
~/.codex/config.tomlworks because it is aUserlayer.-c 'skills.config=...'works because it is aSessionFlagslayer.<repo>/.codex/config.tomldoes not work because it is aProjectlayer.
Why this matters
The docs describe project-local configuration as a configuration layer, and the skills docs describe skills.config as the mechanism for enabling/disabling skills. Users naturally expect those two features to compose.
Selective project-level skill filtering is useful for keeping prompts smaller and avoiding irrelevant automatic skill triggers without losing globally installed skills in other repositories.
5 Comments
Hi — I have a fix ready for this on a fork branch. Sharing here since external PRs are by-invitation only.
Root cause confirmed
skill_config_rules_from_stackincodex-rs/core-skills/src/config_rules.rsfilters layers down toUserandSessionFlagsonly, droppingProject. The check at lines 36–39:This matches your analysis exactly.
ConfigLayerSource::Projecthas precedence25(betweenUser=20andSessionFlags=30), so once the layer is permitted, the existingLowestPrecedenceFirstwalk already produces the correct override semantics with no further changes.bundled_skills_enabled_from_stackuseseffective_config()(full layer merge), which is why the partial workaround[skills] include_instructions = falsealready works at the project level — only the per-skill rule path is gated.There is also direct precedent in the same crate boundary:
codex-rs/core/src/exec_policy.rs:538acceptsUser | Projectas peers for the same kind of layer-source filtering.Fix
Add
Projectto the allowlist:Regression coverage
Three tests added to
codex-rs/core-skills/src/manager_tests.rs:disabled_paths_for_skills_honors_project_layer_name_selector— a Project-only stack disables a skill by name.disabled_paths_for_skills_lets_project_layer_override_user_layer— Project layer correctly overrides aUser-layer disable (precedence).skills_for_config_disables_skill_via_project_layer— end-to-end throughSkillsManager::skills_for_configwith a real Project layer pointing at a<cwd>/.codexfolder.Verification (local)
cargo test -p codex-core-skills --lib→ 99/99 pass (3 new + 96 existing).cargo clippy -p codex-core-skills --tests -- -D warnings→ clean.cargo +nightly fmt -p codex-core-skills -- --check→ clean.cargo check -p codex-core→ clean (downstream consumer).Diff stat: 2 files changed, 116 insertions, 1 deletion.
Branch
Branch (forked, ready to cherry-pick or pull): https://github.com/gabrimatic/codex/tree/fix/project-skills-config-filter
Single commit: https://github.com/gabrimatic/codex/commit/0235d76cdc
Happy to open a PR if a maintainer can grant access, or you're welcome to pull the commit directly. Thanks for the very precise bug report — having
skill_config_rules_from_stackflagged saved a lot of triage time.Hi, thanks for reporting this.
This is actually the current intended design rather than a bug. At the moment, we only support global-level skill enable/disable, as it provides a more consistent overall UX in the Codex app.
I'll change this from a bug report to an enhancement request.
Thanks for clarifying. If global-only skill enable/disable is the current intended design, then treating this as an enhancement request makes sense.
I’d still find project-local selective skill filtering useful for trusted projects, so I appreciate keeping this open for future consideration.
Thanks also to @gabrimatic for confirming the code path and putting together a possible implementation.
This feature request hasn't received enough upvotes, so it is being closed automatically. If you still feel this feature is needed, please open a new feature request with an updated title and description.