fix(doctor): warn on unknown COWORK_VM_BACKEND, document Cowork backend (#324)

Adds:

- `*)` case + valid-values warning on both `COWORK_VM_BACKEND` switches in `scripts/doctor.sh`, factored through a shared `_warn_unknown_backend` helper. Switch A explicitly matches the empty and `bwrap` cases as no-ops alongside `kvm|host` so only truly-unknown values trigger the warn. Switch B (user-facing summary) reports cowork_backend as `auto-detect (invalid override '...' — see warning above)` so the doctor is honest about what the daemon actually does (#442 tracks the daemon-side fix).
- `COWORK_VM_BACKEND` env var row + new Cowork Backend section in `docs/CONFIGURATION.md`, placed before Cowork Sandbox Mounts.
- VM connection timeout / virtiofsd PATH / Fedora tmpfs (EXDEV) sections in `docs/TROUBLESHOOTING.md`.
- README acknowledgment for @CyPack.

Closes #293

Co-Authored-By: aaddrick <aaddrick@gmail.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
CyPack
2026-05-01 05:09:41 +02:00
committed by GitHub
parent 8ac73e6ba9
commit b5339d0f0b
4 changed files with 105 additions and 1 deletions

View File

@@ -209,7 +209,9 @@ Special thanks to:
- Detailed analysis of the CI release pipeline failure caused by runner kills during compare-releases
- Diagnosing the session-start hook sudo blocking issue with three solution approaches
- **[chukfinley](https://github.com/chukfinley)** for experimental Cowork mode support on Linux
- **[CyPack](https://github.com/CyPack)** for orphaned cowork daemon cleanup on startup
- **[CyPack](https://github.com/CyPack)**
- Orphaned cowork daemon cleanup on startup
- `COWORK_VM_BACKEND` documentation, Cowork troubleshooting sections, and unknown-value warning in `--doctor`
- **[IliyaBrook](https://github.com/IliyaBrook)**
- Fixing the platform patch for Claude Desktop >= 1.1.3541 arm64 refactor
- Fixing the duplicate tray icon on OS theme change with an in-place `setImage`/`setContextMenu` fast-path that avoids the KDE Plasma SNI re-registration race

View File

@@ -15,6 +15,7 @@ Model Context Protocol settings are stored in:
|----------|---------|-------------|
| `CLAUDE_USE_WAYLAND` | unset | Set to `1` to use native Wayland instead of XWayland. Note: Global hotkeys won't work in native Wayland mode. |
| `CLAUDE_MENU_BAR` | unset (`auto`) | Controls menu bar behavior: `auto` (hidden, Alt toggles), `visible` / `1` (always shown), `hidden` / `0` (always hidden, Alt disabled). See [Menu Bar](#menu-bar) below. |
| `COWORK_VM_BACKEND` | unset (auto-detect) | Force a specific Cowork isolation backend: `kvm` (full VM), `bwrap` (bubblewrap namespace sandbox), or `host` (no isolation). See [Cowork Backend](#cowork-backend) below. |
### Wayland Support
@@ -48,6 +49,42 @@ CLAUDE_MENU_BAR=visible claude-desktop
export CLAUDE_MENU_BAR=visible
```
## Cowork Backend
Cowork mode auto-detects the best available isolation backend:
| Priority | Backend | Isolation | Detection |
|----------|---------|-----------|-----------|
| 1 | bubblewrap | Namespace sandbox | `bwrap` installed and functional |
| 2 | KVM | Full QEMU/KVM VM | `/dev/kvm` (r/w) + `qemu-system-x86_64` + `/dev/vhost-vsock` |
| 3 | host | None (direct execution) | Always available |
To override auto-detection:
```bash
# Force bubblewrap (recommended if KVM times out)
COWORK_VM_BACKEND=bwrap claude-desktop
# Force host mode (no isolation)
COWORK_VM_BACKEND=host claude-desktop
# Make permanent via desktop entry override
mkdir -p ~/.local/share/applications/
cat > ~/.local/share/applications/claude-desktop.desktop << 'EOF'
[Desktop Entry]
Name=Claude
Exec=env COWORK_VM_BACKEND=bwrap /usr/bin/claude-desktop %u
Icon=claude-desktop
Type=Application
Terminal=false
Categories=Office;Utility;
MimeType=x-scheme-handler/claude;
StartupWMClass=Claude
EOF
```
Run `claude-desktop --doctor` to see which backend is selected and which dependencies are available.
## Cowork Sandbox Mounts
When using Cowork mode with the BubbleWrap (bwrap) backend, you can customize

View File

@@ -134,6 +134,49 @@ Credit: this workaround was contributed by
[@hfyeh](https://github.com/hfyeh) in
[#351](https://github.com/aaddrick/claude-desktop-debian/issues/351).
### Cowork: "VM connection timeout after 60 seconds"
If Cowork fails with a VM timeout, the KVM backend is selected but the guest VM cannot connect back to the host via vsock within the timeout window. Common causes:
1. **First-boot initialization** — the guest VM may take longer than 60 seconds on first launch
2. **vsock driver issues** — the host may be missing the `vhost_vsock` module (`sudo modprobe vhost_vsock`), or the guest initrd may lack `vmw_vsock_virtio_transport`
**Fix:** Force the bubblewrap backend, which provides namespace-level isolation without a VM:
```bash
COWORK_VM_BACKEND=bwrap claude-desktop
```
See [CONFIGURATION.md](CONFIGURATION.md#cowork-backend) for how to make this permanent.
### Cowork: virtiofsd not found (Fedora/RHEL)
On Fedora and RHEL, `virtiofsd` installs to `/usr/libexec/virtiofsd` which is
outside `$PATH`. The `--doctor` check detects it there automatically and will
show `[PASS]`, but the KVM backend spawns `virtiofsd` by name at runtime and
resolves it through `$PATH` only.
**Fix:** Create a symlink so the KVM backend can find it at runtime:
```bash
sudo ln -s /usr/libexec/virtiofsd /usr/local/bin/virtiofsd
```
On Debian/Ubuntu, the same issue can occur with `/usr/lib/qemu/virtiofsd`.
### Cowork: cross-device link error on Fedora tmpfs /tmp
On Fedora, `/tmp` is a tmpfs by default. VM bundle downloads may fail with `EXDEV: cross-device link not permitted` when moving files from `/tmp` to `~/.config/Claude/`.
**Fix:** Set `TMPDIR` to a directory on the same filesystem:
```bash
mkdir -p ~/.config/Claude/tmp
TMPDIR=~/.config/Claude/tmp claude-desktop
```
Or add `TMPDIR=%h/.config/Claude/tmp` to the `Exec=` line in your `.desktop` file.
### Authentication Errors (401)
If you encounter recurring "API Error: 401" messages after periods of inactivity, the cached OAuth token may need to be cleared. This is an upstream application issue reported in [#156](https://github.com/aaddrick/claude-desktop-debian/issues/156).

View File

@@ -93,6 +93,16 @@ _fail() {
_warn() { echo -e "${_yellow}[WARN]${_reset} $*"; }
_info() { echo -e " $*"; }
# Warn about an unrecognized COWORK_VM_BACKEND value. The daemon
# (cowork-vm-service.js) ignores invalid values and falls through to
# auto-detect — see #442 for the daemon-side wart. Called from both
# COWORK_VM_BACKEND case statements below so the warning fires once
# at the severity-gating site and once at the user-facing summary.
_warn_unknown_backend() {
_warn "Unknown COWORK_VM_BACKEND: '${COWORK_VM_BACKEND}'"
_info 'Valid values: kvm, bwrap, host'
}
# Locate the virtiofsd binary. Distros install it at different
# off-PATH locations:
# - Debian/Ubuntu: /usr/libexec/virtiofsd (qemu-system-common)
@@ -566,6 +576,14 @@ print(len(servers))
local _bwrap_active=true
case "${COWORK_VM_BACKEND,,}" in
kvm|host) _bwrap_active=false ;;
''|bwrap) ;;
*)
# Unknown values: warn but leave _bwrap_active=true.
# The daemon falls through to auto-detect, which
# prefers bwrap — keep severity semantics aligned
# with that runtime behavior. See #442.
_warn_unknown_backend
;;
esac
# Bubblewrap (default backend)
@@ -718,6 +736,10 @@ print(len(servers))
kvm) cowork_backend='KVM (full VM isolation, via override)' ;;
bwrap) cowork_backend='bubblewrap (namespace sandbox, via override)' ;;
host) cowork_backend='host-direct (no isolation, via override)' ;;
*)
_warn_unknown_backend
cowork_backend="auto-detect (invalid override '${COWORK_VM_BACKEND}' — see warning above)"
;;
esac
elif command -v bwrap &>/dev/null; then
# bwrap is installed: if the probe succeeds, use it;