[BUG] /config outputStyle picker lists only the 4 built-in styles — a custom style from ~/.claude/output-styles is active but never selectable (2.1.226)
Preflight Checklist
- [x] I have searched existing issues and this has not been reported yet. The closest match is #75351 (closed as duplicate), which reports the inverse case: a plugin style that appears in the picker but never applies. See the regression note below.
- [x] This is a single bug report
- [x] I am using the latest version of Claude Code (2.1.226)
What's Wrong?
A custom output style in ~/.claude/output-styles/ loads and applies correctly, but the /config picker never lists it. The picker offers only the four built-in entries.
Type /config outputStyle= and the completion shows exactly this:
outputStyle=default
outputStyle=Proactive
outputStyle=Explanatory
outputStyle=Learning
My style is active at that moment. The value column of the Output style row shows ASD-STE100, and the status line reports the same name from the output_style.name field of the status-line payload. So discovery works and activation works. Only the list of choices is wrong.
Cause. The 2.1.226 bundle holds the styles in two separate places, and the picker reads the built-in one. The row definition is:
{id:"outputStyle",label:"Output style",
value: Ip("outputStyles") && !Object.hasOwn($ye,o) ? `${o} (disabled in safe mode)` : o,
type:"managedEnum",
options: Object.keys($ye),
optionsHint:"For custom styles, open /config.", ...}
$ye is the static map of built-in styles. It holds [cj]:null where cj="default", plus name:"Proactive", name:"Explanatory" and name:"Learning", each with source:"built-in". That is the four rows above.
The merged map that resolves the active style comes from a different, asynchronous function:
if(Ip("outputStyles")) return {...$ye};
let r = await oQp(t), n = await lFs(), o = {...$ye},
i = r.filter(c=>c.source==="policySettings"),
s = r.filter(c=>c.source==="userSettings"),
a = r.filter(c=>c.source==="projectSettings"),
l = [n,s,a,i];
for (let c of l) for (let u of c) o[u.name] = {...};
return o
This function merges the plugin styles, the user directory, the project directory and the policy settings. The picker row never uses its result, so a style that comes from a file can never appear in the list, whatever its name or frontmatter.
A second sign that this is an oversight. The hint on the row reads "For custom styles, open /config.", and the row itself sits in /config. That text was written for the separate /output-style command, which this version removed. The bundle carries the removal notice: Output styles are configured via \/config\, not \/output-style\. and Output styles still exist as a feature; only the dedicated command was removed. The command went away, its picker moved into /config, and the option list kept the built-in constant.
Why this hurts more than a cosmetic gap. The onChange of the row writes to the local project scope:
let B = await ts("localSettings",{outputStyle:j});
So one pick inside a repository writes outputStyle to that project's local settings, and that value then overrides the global custom style in that repository. The user cannot pick the custom style back, because the name is absent from the list. The only exit is a manual edit of the JSON. A user who does not know the internals reads the short list as proof that the custom style is broken or gone.
Safe mode is not involved. Both restriction maps set outputStyles:!1.
What Should Happen?
The picker lists every style that the resolver can return: the built-in styles, the styles in ~/.claude/output-styles/, the styles in the project directory, plugin styles and policy styles. The active style must always be one of the choices, so a user can switch away and switch back.
Error Messages/Logs
There is no error and no warning. The failure is silent. The evidence is the set of strings in the bundle quoted above.
Steps to Reproduce
- Write
~/.claude/output-styles/my-style.mdwith valid frontmatter:name: My-Style, adescription, andkeep-coding-instructions: true. - Put
"outputStyle": "My-Style"in~/.claude/settings.json. - Start a session. The style applies. A status line that prints
output_style.nameshowsMy-Style. - Type
/config outputStyle=and read the completion. Onlydefault,Proactive,ExplanatoryandLearningappear.My-Styleis absent. - Open
/configand look at theOutput stylerow. The value readsMy-Style, but the list of choices does not hold it. - Pick
defaultfrom the list. The pick lands in the project local settings. Now no path through the UI returns you toMy-Style.
Claude Model
Opus 5 (1M context). The model does not matter for this bug.
Is this a regression?
Yes, this worked in a previous version.
I did not test an old build myself, so I mark this with care. Issue #75351 reports a plugin-provided output style that appeared in the /config picker on 2.1.202, three weeks before the /output-style command was removed. That report is evidence that the list once held styles from outside the built-in map. Issue #64914 (closed as stale) reported a discovery failure and is a different problem.
Last Working Version
2.1.202, per the evidence in #75351. I have not confirmed this against a local install of that build.
Claude Code Version
2.1.226 (Claude Code), native install
Platform
Anthropic API
Operating System
Windows
Terminal/Shell
PowerShell
Additional Information
A workaround for anyone who lands here: the active style is still visible in two places. The value column of the Output style row in /config shows the real name, and the status-line payload holds output_style: { name }, so a status-line script can print it permanently. To change styles, edit outputStyle in the settings JSON by hand, and treat the picker list as read-only.
Two small fixes look sufficient, and they are independent:
- Feed the picker from the merged resolver instead of
Object.keys($ye). - Remove or rewrite the
optionsHint, which now points at the panel that shows it.
3 Comments
Confirmed — independent reproduction on 2.1.226 (Linux ARM64, native installer).
Two custom styles in
~/.claude/output-styles/(valid frontmatter incl.keep-coding-instructions: true,CLAUDE_CONFIG_DIRunset): the/config outputStyle=completion lists only the four built-ins, but the styles load fine when named explicitly.Verified activation end-to-end with a headless probe: with
"outputStyle": "<CustomName>"in settings,claude -p 'If your system instructions contain the phrase "<phrase unique to the custom style>", reply YES, else NO'answers YES; withdefaultit answers NO. So discovery and injection both work — only the picker's option list is wrong, matching the static-map analysis above.Practical impact: users who created a style file conclude the feature is broken, since nothing in the UI ever shows their style exists (this cost us a full debugging session). A one-line fix on impact until the picker reads the discovered set: append discovered custom style names to
options.Thanks for the detailed report. I tested this on the current release (2.1.233) on Linux with a custom style in
~/.claude/output-styles/set as the active style, and can partially reproduce it:/config outputStyle=offers only the four built-in styles — the active custom style is missing from the autocomplete, and picking a built-in there writes a project-local override just as you described./config, moving to the Output style row, and pressing Enter opens a picker that does list the custom style (with its description and a checkmark when active), and selecting it switches back and updates.claude/settings.local.json. So on the current release there is a UI path back after picking a built-in — the dead end you hit doesn't occur here, though I couldn't test 2.1.226 on Windows specifically.The autocomplete list omitting discovered custom styles is a genuine gap and I've flagged it for a fix. Note that the pick saving to the project's local settings is documented behavior (see https://code.claude.com/docs/en/output-styles), so the fix here is making the suggestion list match the styles the dialog and resolver already know about.
If you can, try 2.1.233+ and confirm whether the Enter-on-the-row picker shows your style on your setup too.
🤖 Generated with Claude Code
Confirmed on 2.1.246 (Windows, native install, PowerShell). With
ASD-STE100from~/.claude/output-styles/active, opening/config, moving to the Output style row and pressing Enter now lists every style — the four built-ins plusASD-STE100— and selecting it switches back. So the dead end from the original report is gone on current builds.The
/config outputStyle=autocomplete still lists only the four built-in styles on 2.1.246, so that remaining gap matches your finding on 2.1.233.