Skip to content

fix(doctor): detect virtiofsd outside PATH + document COWORK_VM_BACKEND#324

Open
CyPack wants to merge 1 commit intoaaddrick:mainfrom
CyPack:fix/fedora-cowork-docs-virtiofsd
Open

fix(doctor): detect virtiofsd outside PATH + document COWORK_VM_BACKEND#324
CyPack wants to merge 1 commit intoaaddrick:mainfrom
CyPack:fix/fedora-cowork-docs-virtiofsd

Conversation

@CyPack
Copy link
Copy Markdown

@CyPack CyPack commented Mar 21, 2026

Summary

  • fix(doctor): Detect virtiofsd installed outside $PATH (Fedora /usr/libexec/, Debian /usr/lib/qemu/)
  • docs(config): Document the COWORK_VM_BACKEND environment variable (host|bwrap|kvm)
  • docs(troubleshooting): Add Cowork troubleshooting section (VM timeout, virtiofsd PATH, Fedora tmpfs)

Problem

  1. On Fedora/RHEL, virtiofsd installs to /usr/libexec/virtiofsd which is outside $PATH. The --doctor check uses command -v and reports [WARN] virtiofsd: not found even though the binary is installed. Same issue on Debian/Ubuntu with /usr/lib/qemu/virtiofsd.

  2. The COWORK_VM_BACKEND environment variable exists in cowork-vm-service.js (line 47) but is undocumented in docs/CONFIGURATION.md.

  3. docs/TROUBLESHOOTING.md has no Cowork section at all.

Changes

scripts/launcher-common.sh

  • Added _doctor_find_virtiofsd() helper probing /usr/libexec/virtiofsd and /usr/lib/qemu/virtiofsd
  • Doctor shows [PASS] virtiofsd: found (/path, not in PATH) instead of false warning
  • Doctor Cowork section shows COWORK_VM_BACKEND override when set

docs/CONFIGURATION.md

  • Added COWORK_VM_BACKEND to env vars table
  • Added Cowork Backend section with priority table, override examples, desktop entry

docs/TROUBLESHOOTING.md

  • Added VM connection timeout section (recommends COWORK_VM_BACKEND=bwrap)
  • Added virtiofsd not found on Fedora/RHEL (symlink workaround)
  • Added cross-device link error on Fedora tmpfs /tmp (TMPDIR fix)

Test plan

  • bash -n scripts/launcher-common.sh passes
  • Tested on Fedora 43 (GNOME 48, Wayland, kernel 6.19.8)
  • claude-desktop --doctor correctly detects virtiofsd at /usr/libexec/virtiofsd
  • COWORK_VM_BACKEND=bwrap claude-desktop confirmed working
  • TMPDIR=~/.config/Claude/tmp prevents EXDEV on Fedora tmpfs

Related


Generated with Claude Code
Co-Authored-By: Claude Opus 4.6 (1M context) noreply@anthropic.com
70% AI / 30% Human
Claude: virtiofsd PATH detection, documentation, troubleshooting
Human: testing, review, Fedora-specific validation

Copy link
Copy Markdown
Owner

@aaddrick aaddrick left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey! This is solid work addressing a real pain point. The --doctor false warning on Fedora and Debian has been confusing users since #293, and the documentation additions for COWORK_VM_BACKEND fill a genuine gap. The _doctor_find_virtiofsd() helper is clean and well-structured.

I found two issues in the shell script logic and one potential improvement in how the override is reported. The docs look good overall with one small note.

scripts/launcher-common.sh

Issue 1: Severity mismatch in virtiofsd not-found branch

The existing tool loop uses "$_kvm_issue" to control whether missing tools show as [WARN] (KVM active) or [INFO] (KVM not active). The new elif branch hardcodes _warn and always shows the fix hint. This means when a user hasn't set COWORK_VM_BACKEND=kvm, virtiofsd will show [WARN] while QEMU and socat show as plain info lines. It also always prints the install hint, unlike the other tools which gate it behind $_kvm_active.

Recommendation: Match the existing pattern so all three KVM tools behave consistently.

		elif [[ $_tool_bin == 'virtiofsd' ]]; then
			local _vfsd_path
			_vfsd_path=$(_doctor_find_virtiofsd) || true
			if [[ -n $_vfsd_path ]]; then
				_pass "$_tool_label: found ($_vfsd_path, not in PATH)"
			else
				"$_kvm_issue" "$_tool_label: not found"
				if $_kvm_active; then
					_info \
						"Fix: $(_cowork_pkg_hint \
							"$_distro_id" "$_tool_pkg")"
				fi
			fi

Issue 2: Duplicate COWORK_VM_BACKEND reporting

The new block at the top of the Cowork section prints _info "Backend override: COWORK_VM_BACKEND=...". But the existing code already reports the override in the "Cowork isolation:" line with "(via override)" appended. Running --doctor with COWORK_VM_BACKEND=bwrap would show both. I'd suggest either dropping the early mention since "(via override)" already covers it, or shortening to just _info "COWORK_VM_BACKEND=${COWORK_VM_BACKEND}" so it reads more like a status line.

Issue 3 (minor): :- vs - inconsistency

The new code uses ${COWORK_VM_BACKEND:-} but the existing convention in this file uses ${COWORK_VM_BACKEND-} without the colon. Both work identically for -n tests, but keeping it consistent helps readability.

docs/TROUBLESHOOTING.md

The new sections are well-written. One note: with this PR's _doctor_find_virtiofsd() fix, --doctor will correctly detect virtiofsd at /usr/libexec/. The symlink workaround is still valid for the KVM backend runtime (which spawns virtiofsd by name via PATH), so the advice is correct — might be worth mentioning that distinction. Not blocking, especially since PR #337 just disabled VM downloads on Linux for now.

Summary

  1. Fix severity mismatch — Use "$_kvm_issue" and gate the fix hint behind $_kvm_active (matches existing pattern). This one should be addressed before merge.
  2. Consider deduplicating the COWORK_VM_BACKEND display (minor)
  3. Use ${COWORK_VM_BACKEND-} without colon for consistency (minor)

Written by Claude Opus 4.6 via Claude Code

CyPack pushed a commit to CyPack/claude-desktop-debian that referenced this pull request Mar 23, 2026
Address all three review issues from @aaddrick:

Issue 1 (severity mismatch): Implement _kvm_active/_kvm_issue pattern
to vary severity of KVM-specific tool checks (QEMU, socat, virtiofsd).
When KVM is not the active/intended backend, missing KVM tools show as
plain info lines instead of warnings. bubblewrap always warns since it
is an independent backend.

Issue 2 (duplicate reporting): Remove the separate Backend override
info line. Instead, make the Cowork isolation detection honor
COWORK_VM_BACKEND the same way the daemon does, appending [override]
to the label. Also warn on invalid override values.

Issue 3 (colon convention): Keep :- (with colon) as-is. Audited all
21 parameter expansions in production code: 100% use :- consistently.
The colon correctly treats empty string same as unset, matching the
JS side (process.env.COWORK_VM_BACKEND || null).

Also fix TROUBLESHOOTING.md to clarify that --doctor now detects
virtiofsd at /usr/libexec/ automatically, but the symlink is still
needed for the KVM backend at runtime (spawns by PATH only).

Co-Authored-By: Claude <claude@anthropic.com>
@CyPack
Copy link
Copy Markdown
Author

CyPack commented Mar 23, 2026

Thanks for the thorough review! All three issues addressed in commit d1d62a1.

Issue 1: Severity mismatch (MUST FIX) ✅

Deep dive revealed that $_kvm_issue and $_kvm_active don't exist in the current codebase — all four tools uniformly used _warn. But the intent is absolutely right: KVM-specific tools shouldn't warn when KVM isn't the active backend.

Implemented: Added _kvm_active/_kvm_issue pattern that gates severity based on whether KVM is relevant:

  • COWORK_VM_BACKEND=kvm_kvm_active=true, _kvm_issue=_warn
  • COWORK_VM_BACKEND=bwrap|host_kvm_active=false, _kvm_issue=_info
  • Unset (auto-detect) → checks /dev/kvm accessibility

Applied consistently to all three KVM tools (QEMU, socat, virtiofsd) while keeping bubblewrap as always-_warn since it's an independent backend.

Also restructured the tool loop to use continue for found cases, eliminating code duplication between the virtiofsd elif and generic else branches.

Issue 2: Duplicate reporting ✅

The "(via override)" text doesn't actually exist in the current code — the cowork_backend detection block ignores COWORK_VM_BACKEND entirely. This means on a KVM-capable system with COWORK_VM_BACKEND=bwrap, the doctor shows Cowork isolation: KVM (full VM isolation) while the daemon actually uses bwrap — contradictory output.

Fixed: Made the backend detection mirror detectBackend() faithfully — when COWORK_VM_BACKEND is set, it short-circuits the probe and uses the override directly with an [override] suffix:

       Cowork isolation: bubblewrap (namespace sandbox) [override]

Removed the separate Backend override: info line since [override] carries the information more precisely.

Also added a [WARN] with valid values hint for invalid override values (e.g., COWORK_VM_BACKEND=docker).

Issue 3: Colon convention ✅ (respectfully keeping :-)

Audited all parameter expansions across the entire project: 21/21 production instances use :- (with colon), zero use bare -. The :- form is actually the established convention here.

Semantically, :- is also the correct choice for COWORK_VM_BACKEND — it treats empty string same as unset, consistent with how the JS side handles it (process.env.COWORK_VM_BACKEND || null).

Docs (TROUBLESHOOTING.md) ✅

Clarified the doctor-vs-runtime distinction: --doctor now detects virtiofsd at /usr/libexec/ automatically and shows [PASS], but the symlink is still required for the KVM backend which spawns virtiofsd by name via $PATH at runtime.


Generated with Claude Code
Co-Authored-By: Claude Opus 4.6 (1M context) noreply@anthropic.com
90% AI / 10% Human
Claude: Deep analysis (7 specialist agents), implementation, testing, PR response
Human: Bug report, review direction

Add _doctor_find_virtiofsd() to probe /usr/libexec/virtiofsd (Fedora/RHEL)
and /usr/lib/qemu/virtiofsd (Debian/Ubuntu) when virtiofsd is not in PATH.
Shows [PASS] with the discovered path instead of a false [WARN] not-found.

Add warning for invalid COWORK_VM_BACKEND values with valid-values hint.

Document COWORK_VM_BACKEND in CONFIGURATION.md with priority table,
override examples, and desktop entry persistence.

Add three Cowork troubleshooting sections to TROUBLESHOOTING.md:
- VM connection timeout (vsock/first-boot) with bwrap workaround
- virtiofsd not found on Fedora (doctor vs runtime PATH distinction)
- cross-device link error on Fedora tmpfs /tmp

Co-Authored-By: Claude <claude@anthropic.com>
@CyPack CyPack force-pushed the fix/fedora-cowork-docs-virtiofsd branch from d1d62a1 to de275ef Compare March 30, 2026 15:22
@CyPack
Copy link
Copy Markdown
Author

CyPack commented Mar 30, 2026

Rebased onto current upstream/main (91924b4). The PR is now a clean additive diff — 114 lines added, 0 removed, zero conflict risk.

What changed in the rebase

Dropped everything upstream already implemented since the original PR:

  • _kvm_active/_kvm_issue severity pattern → upstream has this (commit 39c9fea)
  • Backend detection override with (, via override) labels → upstream has this (commit d499d8d)
  • _pass/_warn/_info use $* now → adopted upstream's convention

What remains (all genuinely new)

scripts/launcher-common.sh (+34 lines):

  • _doctor_find_virtiofsd() — probes /usr/libexec/virtiofsd and /usr/lib/qemu/virtiofsd
  • elif in the KVM tool loop for the non-PATH probe
  • Unknown COWORK_VM_BACKEND value → [WARN] with valid-values hint

docs/CONFIGURATION.md (+37 lines):

  • COWORK_VM_BACKEND env var table row
  • ### Cowork Backend section (priority table, override examples, desktop entry)

docs/TROUBLESHOOTING.md (+43 lines):

  • VM connection timeout workaround
  • virtiofsd PATH issue (doctor vs runtime distinction)
  • Fedora tmpfs EXDEV error workaround

Tested: shellcheck clean, --doctor output verified for bwrap/kvm/host/invalid override scenarios.


Generated with Claude Code
Co-Authored-By: Claude Opus 4.6 (1M context) noreply@anthropic.com
90% AI / 10% Human
Claude: Rebase analysis, upstream comparison, implementation, testing
Human: Review direction, scope decisions

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

virtiofsd not found even though it is installed

2 participants