Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
37 changes: 37 additions & 0 deletions docs/CONFIGURATION.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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
Expand Down
43 changes: 43 additions & 0 deletions docs/TROUBLESHOOTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -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).
Expand Down
22 changes: 22 additions & 0 deletions scripts/doctor.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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;
Expand Down
Loading