[BUG] [Cowork] Typing /skill whose !`cmd` fails hangs the cloud session silently (interactive twin of #87159)

Status Open
Reported on v2.1.287
Maintainer reply None cached
Activity 3 comments · opened Oct 2, 2026

Preflight Checklist

  • [x] I have searched existing issues and this hasn't been reported yet. *(The headless version is

#87159, closed by the stale bot. This report covers the interactive Cowork / claude.ai surface,
which #87159 does not.)*

  • [x] This is a single bug report
  • [x] I am using the latest version of Claude Code *(as served to the cloud session on the test

date: 2.1.287)*

What's Wrong?

Related: #87159 (headless -p, same mechanism, closed by the stale bot after it was reproduced),
#80223 (permission-denied variant), #84230 (docs).

In a Claude Code cloud session started from Claude Desktop or claude.ai
(CLAUDE_CODE_ENTRYPOINT=remote_cowork, CLI 2.1.287), a plugin skill whose SKILL.md contains an
inline ` !cmd that fails makes the conversation hang with no feedback when the user **types**
the skill's slash command. Examples of a failing command: a nonexistent command, or
uuidgen`,
which is not installed in the cloud container.

What the user sees:

  • the message bubble, then three typing dots for less than 1 second, then nothing;
  • no reply, no error, no "Loading skill" row, no Stop button, and no status text;
  • the connection indicator stays "Connected".

We watched for 5 minutes or more each time.

In a screen recording of one run, the dots disappear 0.97 s after send. Nothing on screen
changes for the next 275 s. No working or busy state is ever shown. This looks like the turn
ended at once without output, not like a slow load.

The same failing skill behaves correctly when the model invokes it through the Skill tool.
The tool returns ` Shell command failed for pattern "!…" ` and the model recovers. So only the
typed-slash path drops the error.

When it happens:

  • Team org, older Cowork composer: the slash command is the first message of a new conversation.
  • Personal org, newer merged composer: the slash command is sent after an earlier message has

started the cloud session (for example, a first turn that runs a shell command). Happens in
both Desktop and claude.ai web.

When it does not happen: in the merged composer, when the slash command is the first message
of a new chat. In that case the skill is expanded before any cloud session exists, and the
` !cmd ` is never run. No hang, but also no command output.

What Should Happen?

Either the failure is shown (an error row or message such as
` Shell command failed for pattern "!…": … `), or the skill loads in a degraded form with the
error text in place of the command output and the model takes the turn. That is what happens when
the model calls the skill through the Skill tool. The conversation should never be left with no
reply, no error and no way to cancel.

Error Messages/Logs

# Typed slash path (bug): nothing is shown in the UI. No error text appears.

# Model-invoked Skill tool path (skill with !`uuidgen`), the tool result shown to the model:
Shell command failed for pattern "!`uuidgen`": [stderr] /bin/bash: line 3: uuidgen: command not found

# Hypothesis, not verified on this surface (no stream capture was available):
# in headless mode (#87159) the same failure is emitted only as a
#   <local-command-stderr>Error: Shell command failed for pattern "!…": …</local-command-stderr>
# user event, followed by a zero-turn result. The cloud client may receive the same
# zero-turn result and render nothing.

Steps to Reproduce

  1. Create a plugin with one skill. Its SKILL.md must list the command in allowed-tools (as all our runs did) and use it in the body:

``markdown
---
name: probe-skill
description: Probe for failing inline command. Use only when the user asks to run probe-skill.
allowed-tools: Bash(false-probe-cmd-does-not-exist)
---
Command check id: !
false-probe-cmd-does-not-exist`

Report the command check id above.
```

  1. Upload it as an organization plugin and enable it. It syncs into the cloud session under

/root/.claude/plugins/synced/<org-id>_<plugin-id>/….

  1. In Claude Desktop (macOS) or claude.ai (Chrome), open a new conversation in the merged

composer. Send Run date -u in the shell and wait for the tool result.

  1. Type /probe-skill (choose it from the slash menu) and send.
  2. Observed: three dots for less than 1 s, then nothing for 5+ minutes. No error and no Stop

button.

Control: the same plugin with ` !cat /proc/sys/kernel/random/uuid (also listed in allowed-tools`) in place of the failing
command loads normally at step 4. The command output (a fresh UUID) and the plugin path tokens
are filled in, and the model replies within about 20 s.

Variant (Team org, older Cowork composer): send /probe-skill as the first message of a new
cloud conversation. Same hang.

Claude Model

Opus. Two configurations were seen: Opus 4.8 (High) on the Team org and Opus 5.5
(Medium) on the personal org. The bug happens before any model turn, so the model is probably not
a factor.

Is this a regression?

I don't know.

Last Working Version

n/a

Claude Code Version

2.1.287 (Claude Code). This is the agent inside the cloud session
(CLAUDE_CODE_ENTRYPOINT=remote_cowork, CLAUDE_CODE_REMOTE=true). The client was Claude Desktop
2.19675.0 (5706e5) for macOS, and claude.ai in Chrome.

Platform

Anthropic API (Claude subscription: Team plan and Max plan).

Operating System

macOS (the client). The agent runs in Anthropic's Linux cloud container.

Terminal/Shell

Other: no terminal. Claude Desktop app and claude.ai web, cloud session.

Additional Information

Frequency. The hang appeared in every typed run with a failing command: 4 of 4 with a nonexistent command (runs 1-4) and 3 of 3 with uuidgen (runs 5-7):

| # | Org / composer | Client | Position of the slash message | Result |
|---|---|---|---|---|
| 1 | Team / older Cowork composer | Desktop | 1st message | hang, more than 5 min |
| 2 | Team / older Cowork composer | Desktop | 1st message | hang, more than 5 min |
| 3 | Personal / merged composer | Desktop | 2nd, after a shell turn | hang, 5+ min (screen-recorded) |
| 4 | Personal / merged composer | claude.ai web | 2nd, after a shell turn | hang, 5 min 18 s |
| 5 | Team / older Cowork composer | Desktop | 1st message, ` !uuidgen | hang, more than 5 min |
| 6 | Team / older Cowork composer | Desktop | after a model-invoked load of the same skill errored,
!uuidgen | hang, more than 5 min |
| 7 | another Max account,
/chat/ conversation | Desktop | 2nd, after a shell turn, !uuidgen ` | no response, x2 |

The control (same setup as runs 3-4, with a succeeding ` !cmd `) loaded normally in 2 of 2 runs
(Desktop and web).
Not counted above: first-message runs in the merged composer with the failing command, which did not hang (3 runs).

Workaround (not tested by us). Make every ` !cmd in a skill fail-open, for example
!some-cmd 2>&1 || echo "unavailable" `. Avoid binaries that may be missing from the cloud
container. Or ask the model to "run the probe-skill skill" instead of typing the slash command.

Author trap (related, one line). uuidgen is not present in the cloud container, so
` !uuidgen is a realistic way to hit this. cat /proc/sys/kernel/random/uuid` works. See
#84230 for the undocumented rule that a non-zero exit aborts the whole skill load.

Evidence available on request. We have screenshots, a screen recording with frame analysis,
and accessibility-tree dumps.

Not tested:

  • the standalone CLI, interactive (so regression status is unknown);
  • local / VM-loop Cowork (Desktop sessions that are not cloud sessions);
  • Windows or Linux clients;
  • a skill installed some other way than as an org plugin (personal upload, marketplace);
  • whether a command that exists but exits non-zero, or one that times out, behaves the same (we

tested a nonexistent command and a missing binary, uuidgen);

  • whether sending a new message reliably recovers the session, or whether /feedback works

mid-hang;

  • the cloud session's raw event stream (not available to us), so the cause in the client is

inferred, not observed.

View original on GitHub ↗

3 Comments

yaniv-golan · 12 days ago

Correction to the report above :

The hang does not look the same on both composers.

  • Older Cowork composer (runs 1, 2, 5 and 6 in the table): the UI shows "Working on it… · <elapsed time>" with a running timer (we saw up to 5m 36s) and a "Stop response" button. So it is an endless spinner. It is not "no Stop button, no status text", which is how I described it.
  • Merged composer (runs 3 and 4): as reported, there are typing dots for under 1 s, then nothing: no status text and no Stop button.
  • Run 7 was watched for only about 1 minute per attempt, so count it as "no response", not as a 5-minute hang.

Neither composer shows any error, and the model-invoked path still returns ` Shell command failed for pattern "!uuidgen" `. The core bug stands: on the typed path the failure is swallowed.

yaniv-golan · 12 days ago

Second correction: the repro needs allowed-tools. I've updated the steps above.

Every skill in our runs listed its inline command in the frontmatter, for example allowed-tools: Bash(false-probe-cmd-does-not-exist). The original repro sample left that line out.

It matters because each ` !cmd ` goes through the normal Bash permission check (read from the 2.1.286/2.1.287 bundle):

  • allowed: the command runs. If it then fails, you get the hang reported here.
  • needs approval, in auto mode: it is rewritten as a "run this first" instruction.
  • otherwise: the load fails with "Shell command permission check failed".

All the hangs we reported were allowlisted commands that ran and failed. We did not test a failing command that is not allowlisted.

yaniv-golan · 12 days ago

Update: local (non-cloud) Cowork sessions don't run inline commands at all

We tested the "not tested: local" case from the report. Claude Desktop 2.19675.0 (macOS), a local Cowork task ("Only on this computer"), agent 2.1.286.

  • A plugin skill with an allowlisted inline command (` !date -u +%FT%TZ with allowed-tools: Bash(date -u +%FT%TZ)), typed as the first message: the skill text the model receives contains [shell command execution disabled by policy]` in place of the command. We read this in the session transcript on disk.
  • Earlier local runs with a failing command (` !uuidgen `) showed the same placeholder, 2 of 2.

So in local sessions the command never runs. That means no hang, and also no output. The hang described above is specific to cloud sessions, where an allowlisted inline command does run.