Omniscio

OmniscioGuidesClaude Code custom commands

Claude Code custom commands that don't show up

You wrote a command file, or a skill folder, and typing its name offers nothing. In current Claude Code those are one mechanism: a file at .claude/commands/deploy.md and a skill at .claude/skills/deploy/SKILL.md both create /deploy, and existing command files keep working. This guide covers why a command is missing from the / menu, why a different command runs when you type its name, why Claude never reaches for it on its own, and the two closed reports in Anthropic's tracker that explain older breaks.

The shortest path to each thing people actually want.
You wantDo this
To see what loaded in this sessionType /skills
To pick up a file you added a minute agoRun /reload-skills after editing a file in .claude/commands/ or creating a skills folder this session
To be sure the file sits somewhere that loadsA folder at .claude/skills/<name>/SKILL.md, or a file at .claude/commands/<name>.md
To find out why the name was refusedStart with claude --debug and search the log for [names]
To see which command wins a name clashThe precedence table in When a different command runs
To see whether managed settings are in forceRun /status, which lists the active settings sources
Where each question is answered on this page.
You wantRead this
To know how command files and skills relate nowCustom commands are skills now
To know which folders load, and what each name becomesWhere the file has to be
To check what the running session actually hasCheck what actually loaded
To work out why it never appears in the menuWhy it is missing from the menu
To work out why another command answersWhen a different command runs
To fix arguments or a shell line that never ranWhen it runs, but not the way you wrote it
To make Claude reach for it without being askedWhen Claude never picks it up
To know what happens outside a terminal sessionOutside an interactive terminal session
To read the reports this page leans onReports from Anthropic's tracker

Checked against Claude Code 2.1.310 documentation, read on October 26, 2026. No session was run on our side to reproduce a missing command. By the Omniscio team. Updated .

Custom commands are skills now

Anthropic's own note is short and it explains most of this page: custom commands have been merged into skills. A file at .claude/commands/deploy.md and a skill at .claude/skills/deploy/SKILL.md both create /deploy and work the same way, and existing command files keep working. A setup built before the merge is not broken by it.

The documentation has no custom-commands page of its own any more: the old slash-commands address now serves the skills page, which is where these rules live at 2.1.310.

What the newer format adds is room. A command file is one Markdown file in .claude/commands/, project or global, and it takes the same frontmatter as a skill except name and paths. A skill is a folder with a SKILL.md inside it, which can carry supporting files, frontmatter that decides who may invoke it, and a description Claude uses to load it by itself when the work matches.

For a command that will not appear, the format is almost never the cause, which is why everything below applies to both. The causes are where the file sits, what it is called, whether the session has scanned it, and whether another command already owns that name.

Where the file has to be

Where you save the file decides which sessions load it, and the list is longer than most people expect.

The places Claude Code loads skills from.
LocationPathLoads in
Enterprise.claude/skills/<name>/SKILL.md in the managed settings directoryEvery user on machines where the organization deploys it
Personal~/.claude/skills/<name>/SKILL.mdAll your projects on this machine, but not Cowork or cloud sessions
Project.claude/skills/<name>/SKILL.mdSessions in this repository, but not cloud threads in a project
Nested<subdir>/.claude/skills/<name>/SKILL.mdSessions started in or below that subdirectory, or a session started above it once Claude works on files there, but not cloud threads in a project
Added directory.claude/skills/<name>/SKILL.md in a directory passed with --add-dirThat session
Plugin<plugin>/skills/<name>/SKILL.mdWherever the plugin is enabled, as /plugin-name:skill-name
claude.ai accountA skill enabled for your accountCowork sessions, sessions Anthropic hosts, and terminal sessions signed in with that account

A command file follows the same two scopes with a different folder: .claude/commands/<name>.md in the project, or ~/.claude/commands/<name>.md for every project on this machine.

The name you type comes from where the file lives and, for a skill folder, from its frontmatter name. A folder named deploy-staging gives /deploy-staging, and adding name: deploy inside it makes /deploy work as well. A command file takes its name from the file name, and a subfolder becomes a colon, so .claude/commands/frontend/component.md is /frontend:component.

Two namespaces are worth knowing before you rename anything. A plugin's skill always carries the plugin prefix, so both a plugin skill and your own skill of the same name can load at once. A skill synced from your claude.ai account answers to /anthropic-skills:<name> and only owns the bare /<name> while nothing else uses it.

A .claude/skills/ folder below the directory you started in is not loaded at startup. It loads the first time Claude reads or edits a file in that subdirectory, and until then it is not in the / menu and typing its name does not run it. To load it sooner, run /add-dir with that path, which needs Claude Code 2.1.257 or later.

Claude Code watches the skills folders it already knows about, except in bare mode, so a SKILL.md you add or edit during a session is picked up without a restart, and the watch covers the skill's text only. The watch is documented for skills folders, not for a commands/ folder, so after adding or editing a file in .claude/commands/ run /reload-skills, which re-scans skill and command directories. Two more cases fall outside the watch. A top-level skills folder that did not exist when the session started is not watched, so run /reload-skills after creating it and again after later changes there. And a directory passed with --add-dir has its .claude/commands/ read at startup but not watched, so restart the session with the same --add-dir after changing a command file in one.

Check what actually loaded

Start with the list, not the file. /skills shows the skills from your project, your user folder and your plugins, with the source of each, and you can type to filter it. /context shows the skills among what is filling the context window, and adds the bundled ones /skills leaves out. The two answers send you down different paths: a command missing from both did not load, while a command present in one and absent from the / menu is being hidden rather than failing.

  1. Look in /skills Type /skills in the session. It lists the skills from your project, your user folder and your plugins, with the source of each. A command that is missing here did not load at all. A command that is here but absent from the / menu is usually hidden by a setting rather than broken.
  2. Reload the list A file added to a skills folder the session already watches loads by itself. After adding or editing a file in .claude/commands/, run /reload-skills, and run it too for a skills folder created after the session started. If the file is a command file in a directory passed with --add-dir, restart the session with the same --add-dir.
  3. Check the name Start Claude Code with claude --debug and search the log for [names]. A name holding a hidden character, a blank other than one plain space between words, an angle bracket, or more than 256 characters is refused with a startup notice: either the command never loads, or only its name field is ignored.
  4. Check who else owns the name Enterprise beats personal, personal beats project, a skill beats a command file, and a skill synced from your claude.ai account loses its short name to any other command that already uses it.
  5. Check the kind of session Outside an interactive terminal session, in a -p run, an SDK app, a cloud session or a chat panel, an unrecognised name is not reported as an error. It is sent to Claude as ordinary text with a note that the command did not run, and a list of the commands that session can run.

The reload command is blunt on purpose: /reload-skills re-scans the skill and command directories and reports how many are available and how many were added or removed, which is the confirmation people want after saving a file. When you have just saved a file and the menu has not caught up, run /reload-skills before you start suspecting a bug.

The documentation names no shell command that prints the list before a session starts. The check is one of the in-session commands above, or the debug log the session writes at ~/.claude/debug/<session-id>.txt, which is also where a refused name is spelled out.

Safe mode is worth knowing about, but it is not a test for a missing command. claude --safe-mode starts a session with custom commands, skills, plugins, hooks, MCP servers and CLAUDE.md switched off, so every command of yours is missing there by design and nothing is learned. It separates a different kind of problem: a command that runs and behaves oddly because something in your setup, such as a hook or another customization, is interfering. If that problem disappears in safe mode, the cause is one of the things it turned off.

Two failures have a documented answer in one line each. A skill saved as .claude/skills/name.md, a file where a folder belongs, never appears in /skills at all; it needs the folder with SKILL.md inside. And a skill that /skills lists but Claude never invokes carries a user-only badge when disable-model-invocation: true is set, which tells you the command is fine and the automatic trigger is off.

The menu is a view of what loaded, so a missing row means a missing command or a hidden one. These are the cases worth checking first.

What you see, and what it usually means.
What you seeWhat it usually is
It is not in /skills eitherThe file is in the wrong shape or place, such as .claude/skills/name.md instead of a folder with SKILL.md inside, or inside no location that loads
It is not in /skills and you saw a startup noticeClaude Code refused the name, so the command never loaded
It is in /skills but not in the / menuuser-invocable: false in the frontmatter, or a skillOverrides entry set to off
It does not appear after you added it mid-sessionNothing has re-scanned it: a new top-level skills folder, a command file added to .claude/commands/ this session, or a command file in an --add-dir directory's .claude/commands/
It is missing in one project onlyA nested .claude/skills below where the session started, which loads only once Claude works there
It is missing in a cloud or Cowork sessionThose sessions do not read ~/.claude/skills on your machine
It is missing for everyone on the teamA managed policy that allows customization only from plugins

One cause is not in the table because it is not about the file at all. A release regression kept correct command files out of the menu, while a Homebrew install or a ripgrep configuration on the machine stopped the folder being read at all. Both reports at the end of this page cover those cases.

A refused name is the one case where Claude Code tells you directly. The startup notice opens 1 skill or command name refused: run with --debug to see which ([names]), rename, then restart and continues a name may not hold hidden, direction-changing or blank-like characters, < or >, or be over 256 characters, and it means at least one name was refused. Either the command never loaded, or only a frontmatter name was refused, in which case the skill still loads under its folder name. Names cannot hold hidden characters such as a zero-width space, direction-changing characters, the characters < or >, a blank other than one plain space between words, or more than 256 characters. The debug log spells some hidden characters out by code, so you can often see where the problem is. Since 2.1.299, a file or folder name holding those characters is no longer offered until it is renamed.

The other refusal is a reserved name. A skill folder, a frontmatter name, or a file or subfolder in .claude/commands/ called anthropic-skills, or starting with anthropic-skills:, does not load, because that namespace belongs to skills synced from your claude.ai account. The notice names the first item to rename and counts the rest, with each one in the debug log. Since 2.1.282 these names are refused where earlier versions loaded them.

A command that loaded but cannot be seen is a setting, not a fault. user-invocable: false in the frontmatter hides the skill from the / menu and stops /name from running it, which is the right choice for background knowledge and the wrong one for a command you typed. The same hiding is available from settings as skillOverrides, whose off value hides a skill from both Claude and autocomplete, and whose user-invocable-only value does the reverse of the frontmatter field. Plugin skills are managed through /plugin instead.

An organization can also remove the whole category. A managed strictPluginOnlyCustomization policy locks skills, agents, hooks or MCP servers to plugins and managed settings, so a project or personal skill never loads. There is no separate check for it in the session: /status names the settings sources in effect, including whether managed settings are, and the administrator who set the policy is the one who can say whether it locks skills.

When a different command runs

Two commands can share a name, and the documentation is explicit about which one answers. This is also the answer when your command is in /skills and something else runs anyway.

Which command runs when two share a name.
Same name inWhich one runs
Two of enterprise, personal and projectEnterprise over personal, and personal over project
A skill and a file in .claude/commands/The skill
Your skill and a bundled skill or built-in commandYours replaces it, but not its aliases, and a built-in command only in a local terminal session: a project code-review skill replaces /code-review, and the bundled /review still runs Anthropic's
A skill in an --add-dir directory outside the project and one at enterprise, personal or project levelThe local one keeps the name, and the added directory's skill runs as /<folder>:<name>, on 2.1.309 or later
A plugin skill and a skill at any local levelBoth load, because plugin skills are namespaced as /plugin-name:skill-name
Your command and a skill synced from claude.aiYours keeps the short name, and the synced one runs only as /anthropic-skills:name

The synced-skill row is the one that surprises people, because nothing on your machine changed. Once a claude.ai account is signed in, its skills download into ~/.claude/skills/synced/ and can arrive with the same name as one of your commands. Yours keeps the short name, and the synced one moves to /anthropic-skills:<name>. /skills groups them under claude.ai sync and prints a note under the list saying which one lost its short name, and, when the name is held by one of your own skills or command files in ~/.claude/, what to rename or delete to free it.

The menu itself also deserves a mention, because the failure looks like a broken command. Claude Code highlights a suggestion only when what follows the / matches a name or alias from its start or from a word inside it, ignoring the :, _ and - separators, and after a typo nothing is highlighted: pressing Enter submits your text as typed and answers Unknown command with the closest name it knows. Commands that are unavailable in your session are left out of the menu entirely, and when nothing matches you get No commands match.

When it runs, but not the way you wrote it

A command is recognised only at the start of a message, and the text after its name becomes its arguments, which is the part that goes wrong without a message. Up to six skills can be chained in one message, with the trailing text passed to each of them as arguments.

The placeholders are simple once you know the shapes. $ARGUMENTS expands to everything after the command name. $ARGUMENTS[0] and its shorthand $0 are the first argument, $1 the second, and a named list in frontmatter turns $issue into the first argument and $branch into the second. Values are split with shell-style quoting, so /my-skill "hello world" second gives $0 the value hello world.

Two outcomes look like the command ignored your input. An indexed placeholder with no matching argument stays in the content unchanged, so $2 in a command called with one argument reaches Claude as the text $2, while a named placeholder with no argument expands to an empty string. And an argument value that itself contains $1 or $ARGUMENTS is inserted as literal text rather than expanded. To write a dollar sign before a digit in your own prose, escape it with a backslash, as in \$1.00.

A shell line inside a command fails loudly, but the failure can look like the command itself did nothing. The !`command` form runs before Claude sees the file and its output is inlined, and a failure there aborts the whole invocation: a command that fails stops the skill with Shell command failed for pattern, where with the default shell any non-zero exit counts as a failure except exit code 1 from a search or comparison command, and a command containing a raw control character other than tab or newline is refused before any of the file's commands run, with a message naming the tool and showing each unprintable character as �. A skill synced from claude.ai is a third case: its ! commands run only in a session Anthropic hosts, a Cowork session replaces each line with a placeholder, and in any other session on your machine the line reaches Claude as literal text.

When Claude never picks it up on its own

A command that works when you type it and never fires on its own is usually a description problem. Claude decides from the description, so the words a person would naturally use belong at the front of it, and the documented checklist is to check those keywords, ask what skills are available, rephrase the request, then invoke the command directly; if /name is not recognised either, the next check is whether the name was refused.

One frontmatter field turns automatic use off on purpose. disable-model-invocation: true keeps the skill out of Claude's reach while leaving /name working, and /skills marks it user-only, so a reader who did not write the file can see why it never volunteers.

The listing has a budget, and it can weaken automatic use without breaking anything. Claude Code loads a list of skill names and descriptions so it knows what is available; when the list overflows its budget, which scales at one percent of the model's context window, it drops descriptions starting with the skills you invoke least, while every name stays. A skill whose description was dropped still runs as /name and only loses its chance of being chosen automatically. /doctor estimates the listing's cost, and the budget can be raised with skillListingBudgetFraction or a fixed character count in SLASH_COMMAND_TOOL_CHAR_BUDGET.

Malformed frontmatter is the quietest cause. If the YAML between the markers does not parse, the skill still loads with no fields set, so /name works while the description Claude matches on, and any name: alias, do not, and claude --debug shows the parse error.

A paths field narrows when a skill is loaded automatically, and it only matches files inside Claude's current working directory.

A skill written for one part of a monorepo therefore stays quiet when the session is pointed somewhere else, including at a sibling worktree you added with /add-dir.

Outside an interactive terminal session

The / menu and the Unknown command message belong to an interactive terminal session, and if you got here from an Unknown command message, the Claude Code error messages guide covers that message in full. In a -p run, an Agent SDK application, the Code tab of the desktop app, the VS Code chat panel, a cloud session or a cloud scheduled task, an unmatched name is sent to Claude as a normal message with a note that the command did not run and a list of the commands it can run. A command that did load still works there; what you lose is the error message, and a typo costs a wasted turn. The note Claude receives lists the commands that session can run, so asking Claude what it has available is the confirmation there.

Cloud and Cowork sessions also change where the file has to live. They do not read ~/.claude/skills on your machine, so a personal command that works locally is absent there. To use it in one of those sessions, enable it for your claude.ai account. Committing it to the repository's .claude/skills/ also works in a cloud session that is not a project thread, but not in a project's cloud threads and not in Cowork, and plugins declared only in your user settings do not load in cloud sessions either.

In an Omniscio session

Omniscio runs each Claude Code session through the claude binary, so the commands described here belong to that session, and a session on an engine that does not run the claude binary, such as Codex or OpenCode, has none of them. The composer has its own / list, built from the skills in your ~/.claude/skills, the current project's .claude/skills, and your plugins, so a skill folder appears there and a legacy .claude/commands file does not. That list is behind the skillSlashAutocomplete setting, which is on by default.

Typing a name the app does not recognise is still worth trying: the app hands the line to the Claude Code session, which runs custom commands and skills that arrive as user text, and its own /help describes custom commands as passing straight through. What no menu exists for is the confirmation. If a command works when typed and never appears in the composer list, that is the difference between the app's list and the CLI's, not a broken file.

Reports from Anthropic's tracker

The two reports below are the ones this page leans on, and both were filed against a build with the symptom this page is about: a command file that was correct and still did not appear. An issue tracker is a record of what people hit, not a changelog, so each row carries the version in the report and the state it was in when read.

The reports this page cites.
IssueWhat it reportsFiledState
#42038Custom commands in .claude/commands/, top level and in subfolders, stopped appearing in autocomplete on 2.1.89alp-well, 2026-04-01closed as a duplicate of #41864, fixed as of 2.1.91 per the closer
#8831Command files in ~/.claude/commands/ were not discovered at all on 2.0.5Dingzeefs, 2025-10-03closed; the maintainer said it should be resolved in the next release

The first is a regression report, and its thread is the useful part: the closer closed it automatically as a duplicate of #41864, and said that issue was fixed as of 2.1.91. Two reporters in the thread had found their own way out before that, one by installing with the native installer rather than npm, and one workaround was to phrase the request instead of typing the command.

The second is older and has a different cause. Command files were not being found on 2.0.5, and the thread collects several fixes that worked for different people: switching from a Homebrew install to npm, clearing a custom RIPGREP_CONFIG_PATH whose colour settings broke the directory scan, setting USE_BUILTIN_RIPGREP=0, and, on WSL, following another thread's fix (#9518). A maintainer closed it by saying it should be resolved in the next release, which it said would also drop support for custom ripgrep configs.

Neither report describes the build you are running, and neither is a reason to stop checking the file. What they do establish is that the failure has appeared both as a genuine regression and as a local configuration clash, which is why the checks above start with what loaded rather than with the command itself.

Sources

Anthropic's Claude Code documentation, at Claude Code 2.1.310, the newest release listed in the changelog and dated October 23, 2026:

  • Extend Claude with skills: the note that custom commands merged into skills, the locations table, the command name rules, invocation control, arguments, and the troubleshooting section for a skill that will not trigger. Read October 26, 2026.
  • Commands: /skills, /reload-skills, and how the command menu matches what you type. Read October 26, 2026.
  • Debug your configuration: /context, /skills, /doctor and /debug, the common-cause table, and safe mode. Read October 26, 2026.
  • Errors: Unknown command, the refused-name startup notice, the reserved-name notice, and the refusal when a shell line holds control characters. Read October 26, 2026.
  • The Claude directory: commands/*.md as single-file prompts at project and global scope, and the frontmatter they accept. Read October 26, 2026.
  • Settings reference: skillOverrides, skillListingBudgetFraction and strictPluginOnlyCustomization. Read October 26, 2026.
  • The changelog: the newest release, 2.1.310, and the 2.1.299 and 2.1.282 notes on refused and reserved names. Read October 26, 2026.
  • Anthropic's Claude Code issue tracker: the reports in the table above and their threads, read through GitHub's API the same day. Read October 26, 2026.

Omniscio's own pages and source, for what this page says about this app:

  • Native slash commands in the library: that the commands run in the underlying Claude Code session and only for Claude Code sessions. Read October 26, 2026.
  • Our own source: that only Claude Code sessions run the claude binary, that the composer's / list comes from the skills folders and plugins, and that a name it does not recognise is passed through to the session. Read October 26, 2026.

Common questions

Why does my custom slash command not show up in Claude Code?

The file did not load, or something hides it. Type /skills: a command missing there never loaded, usually because of its location or its name. A command listed there but absent from the / menu is hidden by user-invocable: false or a skillOverrides entry, or another command owns the name.

Do I have to move my .claude/commands files into skills?

No. A file at .claude/commands/deploy.md and a skill at .claude/skills/deploy/SKILL.md both create /deploy and work the same way, and existing command files keep working. A skill adds a folder for supporting files and frontmatter for invocation control, so the newer format is worth using for new work.

Why does typing my command name say Unknown command?

In a terminal session, Claude Code answers an unmatched name with Unknown command and suggests the closest one it lists. The documented causes are a typo the suggestion did not catch, a built-in that is unavailable in this session because a requirement such as your platform, plan or authentication is not met, and a plugin or MCP command whose plugin or server is not connected. If none of those fits, the command did not load: check its folder and run /reload-skills. Outside a terminal session the text goes to Claude as a normal message instead.

Why does a different command run when I type my command's name?

Two commands share the name and one has priority. Enterprise beats personal, personal beats project, a skill beats a command file, and a skill synced from your claude.ai account loses its short name to any command already using it. Rename one of them, or invoke the synced one as /anthropic-skills:name.

Why does Claude never use my command on its own?

Claude picks a skill up from its description, so write the words a person would use. A skill with disable-model-invocation: true is manual only and carries a user-only badge in /skills. If you have many skills, the listing can drop descriptions to fit its budget while keeping every name, which leaves /name working and automatic use weaker.

Why do the placeholders in my command show up literally?

An indexed placeholder with no matching argument stays exactly as you wrote it, so $2 in a command called with one argument reaches Claude as the text $2. A named placeholder from the arguments frontmatter expands to an empty string instead. Check the call for missing arguments or for quoting that split one value into two.

Do custom commands work in a -p run or a hosted session?

They can load, but an unmatched name is not reported as an error there: a -p run, an SDK app and a hosted session send the text to Claude with a note that the command did not run. Personal skills in ~/.claude/skills are not read in Cowork or hosted sessions, so enable the skill for your claude.ai account, or commit it to the repository for a hosted session that is not a project thread.

What does a skill or command name refused notice mean?

Claude Code refused a name. Either the command did not load, or, if only a frontmatter name was refused, the skill still loads under its folder name. Names cannot hold hidden or direction-changing characters, a blank other than one plain space between words, an angle bracket, or more than 256 characters. Start with claude --debug and search for [names]: each refused name has one line saying which of the two happened.

Keep those sessions in one window

Omniscio is a desktop app for running several agent sessions side by side. Any model, any harness — Claude Code, Codex, OpenCode, Devin, Pi, and Hermes all supported. The features page lists what is in it today.