103 Commits

Author SHA1 Message Date
aaddrick
b017c72e8f docs(readme): credit Hayao0819 for About window titleBarStyle diagnosis and fix (#481, #489)
Co-Authored-By: Claude <claude@anthropic.com>
2026-05-15 18:53:42 -04:00
aaddrick
04f9a18b69 docs(readme): credit JoshuaVlantis for RPM SUID, autoUpdater no-op, and node-pty install hardening (#539, #567, #401)
Co-Authored-By: Claude <claude@anthropic.com>
2026-05-14 07:19:45 -04:00
aaddrick
fd352f4390 docs(readme): credit jslatten for KDE Wayland desktopName fix (#562)
Co-Authored-By: Claude <claude@anthropic.com>
2026-05-03 08:22:32 -04:00
aaddrick
0c99f2119f docs(readme): credit ProfFlow for re-fix of RPM repodata signing (#566)
Co-Authored-By: Claude <claude@anthropic.com>
2026-05-03 07:44:54 -04:00
sirfaber
244c08a3bd fix(cowork.sh): allow $ in minified identifier anchors; defensive lastIndexOf (#555)
Two regex anchors in patch_cowork_linux() used \w+ to capture minified
identifiers, but on Claude Desktop 1.5354.0 those identifiers contain $
(e.g. C$i, g$i). \w excludes $, so the inner captures never matched:

- Patch 2b (vm: module assignment) silently no-op'd — no warning, no
  failure. Build log went from "Applied 12" to "Applied 10".
- Patch 6 step 2 (retry-delay auto-launch) emitted a warning but still
  failed to apply.

Either way, the resulting app.asar shipped half-patched and Cowork
startup failed at runtime with "Swift VM addon not available".

The fix widens both inner captures from \w+ to [\w$]+, matching the
existing precedent at scripts/patches/cowork.sh:482-501 (introduced in
PR #421 for the $e fs-reference rename in 1.3109.0). Also switches
Patch 6 from indexOf to lastIndexOf for the "VM service not running"
anchor — defensive against future versions reintroducing the string
outside the retry-loop site.

Verified end-to-end on Fedora 43 / KDE Plasma 6 / Wayland: build log
shows "Applied 12 cowork patches"; daemon auto-launches at startup
with clean lifecycle (startup → listen → SIGTERM exit code=0).
Follow-ups tracked in #559.

Resolves #558. Likely resolves #553 (named symptom) and #445 (daemon
never auto-spawned on Linux).

Co-authored-by: Joost-Maker <66303669+Joost-Maker@users.noreply.github.com>
Co-authored-by: HumboldtJoker <19808525+HumboldtJoker@users.noreply.github.com>
Co-authored-by: zabka <3833286+zabka@users.noreply.github.com>
2026-05-02 08:53:02 -04:00
Travis
c973f4922b docs(readme): credit cbonnissent for bwrap {src, dst} mount form (#543)
Adds the new bullet under their existing entry for the
coworkBwrapMounts {src, dst} polymorphic form merged in #531,
which closed #530.

Refs #530, #531
2026-05-01 00:50:02 -04:00
CyPack
b5339d0f0b 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>
2026-04-30 23:09:41 -04:00
Liz Fong-Jones
412b267710 fix(autostart): route openAtLogin through XDG Autostart on Linux (#450)
* fix(autostart): route openAtLogin through XDG Autostart on Linux (#128)

Electron's app.getLoginItemSettings()/setLoginItemSettings() are
no-ops on Linux (electron/electron#15198), so the "Run on startup"
toggle never persists and isStartupOnLoginEnabled() returns
undefined, failing the IPC handler's typeof === 'boolean' check.

Intercept both calls in frame-fix-wrapper.js and back them with
~/.config/autostart/claude-desktop.desktop, which is honoured by
GNOME/KDE/XFCE/Cinnamon/MATE/LXQt (XDG Autostart spec). Also
coerce executableWillLaunchAtLogin (Windows-only in Electron,
undefined on Linux) to a boolean so the IPC handler stops
throwing.

Fixes #128

Co-Authored-By: Claude <claude@anthropic.com>

* fix(autostart): address review — APPIMAGE runtime target, XDG_CONFIG_HOME, StartupWMClass (#128)

Addresses review comments on #450:

- Resolve Exec= and Icon= at toggle time via process.env.APPIMAGE
  so AppImage users (who don't have claude-desktop on $PATH unless
  integrated via AppImageLauncher) get an autostart entry that
  launches the actual .AppImage bundle instead of a broken binary
  reference. escapeExecArg() handles Desktop Entry Exec escaping
  (quote + backslash-escape reserved chars).

- Honour $XDG_CONFIG_HOME when set and non-empty, falling back to
  ~/.config only otherwise. Home-manager and dotfile users who
  relocate the config root were getting the entry dropped in the
  wrong place silently.

- Add StartupWMClass=Claude to the generated entry, matching the
  value set by scripts/packaging/{deb,rpm}.sh, so DEs group the
  autostarted window with user-launched instances under a single
  taskbar/dock item. Drop Categories= per review guidance
  (autostart parsers ignore it).

- Comment why opts.path is intentionally ignored: process.execPath
  points at the electron binary, not the launcher shim that sets
  ELECTRON_FORCE_IS_PACKAGED / ozone flags / orphan cleanup —
  honouring opts.path would write a broken autostart entry.

The "removed" log placement (review item 4) is already inside the
inner try, so unlinkSync throwing ENOENT short-circuits before the
log runs. Left as-is.

Co-Authored-By: Claude <claude@anthropic.com>

* docs(readme): credit lizthegrey for XDG Autostart contribution

Co-Authored-By: Claude <claude@anthropic.com>

---------

Co-authored-by: Claude <claude@anthropic.com>
Co-authored-by: aaddrick <aaddrick@gmail.com>
2026-04-28 19:02:47 -04:00
Liz Fong-Jones
8530342b2e fix(lifecycle): hide main window to tray on close, Linux (#451)
* fix(lifecycle): hide main window to tray on close, Linux (#448)

Electron's default window-all-closed handler quits the app on
Linux. The existing tray icon and Ctrl+Q patches keep the app
reachable while a window is alive, but as soon as the last
window is closed (stray click on X, or a sign-out flow that
closes mainWindow) the app exits and the tray goes with it —
taking any in-app schedulers / MCP servers / cron tasks
(/schedule skill) down silently until the user re-launches.

Intercept BrowserWindow.close on main windows (not popups;
Quick Entry and About already dismiss via hide(), never emit
close) and preventDefault + hide unless app is in a real quit
path. The quit path is detected via before-quit: Ctrl+Q, tray
Quit, cmd+Q, SIGTERM and app.quit() from anywhere all emit
before-quit, which arms app._quittingIntentionally so the
close handler lets the window actually close.

Gated by CLOSE_TO_TRAY, default on. Set CLAUDE_QUIT_ON_CLOSE=1
to restore the Electron-default behaviour.

Fixes #448

Co-Authored-By: Claude <claude@anthropic.com>

* fix(frame-fix-wrapper): drop superseded globalShortcut Ctrl+Q

Removes the globalShortcut.register('CommandOrControl+Q') block
that #484 superseded with the per-window
webContents.on('before-input-event') listener. Auto-merging main
into this branch left both registrations in place, which would
re-introduce the AZERTY physical-keycode grab and system-wide
shortcut steal that #484 fixed. The focus-scoped listener
already covers the original #321 hidden-menu-bar use case.

Also updates the close-to-tray comment to reference the new
listener path instead of the removed global shortcut.

Co-Authored-By: Claude <claude@anthropic.com>

* docs(readme): credit lizthegrey for close-to-tray contribution

Co-Authored-By: Claude <claude@anthropic.com>

---------

Co-authored-by: Claude <claude@anthropic.com>
Co-authored-by: aaddrick <aaddrick@gmail.com>
2026-04-28 18:16:56 -04:00
Andrej730
d4db72865b fix: update visibility function regexp (#496)
* fix: update visibility function regexp

* fix(quick-window): tolerate optional var decl in visibility regex

Make the `var <name>(,<name>)*;` prefix optional so the regex
matches both the older shape (`function L7A(){return!Ct...}`,
1.3109.0) and the current one (`function aZA(){var e;return!Qt...}`,
1.3883.0). The minifier hoists `var e;` whenever the function body
uses optional chaining; if a future release adds `var e,t;` or
drops the var entirely, this still matches without another
chase-the-shape PR.

Verified end-to-end on the live 1.3883.0 build asar: extracts
`pF` / `aZA`, patches both Quick Entry anchor sites
("Navigating to existing chat", "Creating new chat with
submit_quick_entry"), JS validates, idempotent re-run confirmed.
Confirmed against the 1.3109.0 build-reference shape too.

Repro of #390 on Nobara KDE Plasma 6 (Wayland): quick-entry
submit now reliably shows the main window post-patch; no
regressions in regular chat or window restore flows.

Co-Authored-By: Claude <claude@anthropic.com>

* docs(readme): credit @Andrej730 for visibility regex fix (#495)

Co-Authored-By: Claude <claude@anthropic.com>

---------

Co-authored-by: aaddrick <aaddrick@gmail.com>
Co-authored-by: Claude <claude@anthropic.com>
2026-04-27 09:20:46 -04:00
IliyaBrook
cf2b0fc357 fix: update Linux tray icon in place on OS theme change (#515)
* fix: update Linux tray icon in place on OS theme change

Avoids a StatusNotifierItem re-registration race on KDE Plasma
where the old SNI remains registered when the new one appears,
resulting in two tray icons side by side until session logout.

`patch_tray_menu_handler` already bounds the race with a 250 ms
delay after `tray.destroy()`, but that's not enough on all setups
(reproduced on Fedora 43 KDE Plasma 6.6.4 + Wayland). Widening the
delay just moves the goalposts; the race is structural.

Fix: inject a fast-path before the existing destroy+recreate block
in the tray rebuild function. When the tray already exists and
isn't being disabled, update its icon and context menu in place
via `setImage` + `setContextMenu` — the existing StatusNotifierItem
stays registered, no DBus re-registration, no race. The slow path
(destroy + delay + re-create) is kept for the initial creation and
the tray-disable cases where it's unavoidable.

All five minified locals needed by the fast-path (tray function,
tray variable, electron module, menu function, icon path const,
menuBarEnabled flag) are extracted dynamically; the idempotency
guard re-keys off the post-rename `setImage(...)` sequence.

Triggered in KDE System Settings by any of Appearance → Colors /
Plasma Style / Global Theme, which all fire the same
`nativeTheme.on('updated')` signal.

Follow-up to #491. The broader submenu work from that PR stays
parked on features/change-icon-color pending the scope discussion
in #492; this PR ships only the duplicate-tray-icon fix that
@aaddrick asked to split out.

Co-Authored-By: Claude <claude@anthropic.com>

* fix(tray): tighten in-place patch extraction guards

Drop the redundant `electron_var_re_local` local — `electron_var_re`
is already a sourced global from `_common.sh` with the same value.

Replace the silent `head -1` on `enabled_var` extraction with an
explicit count-and-bail. The grep matches `const X=fn("menuBarEnabled")`
across the whole file; today there's exactly one site (inside the
tray function), but if upstream ever ships a second the previous
code would silently bind to whichever the minifier emitted first.
Bail loudly with a count diagnostic instead.

Verified on the live 1.3883.0 build asar: all five extractions
resolve (`Nh`/`wAt`/`t`/`e`) — note the symbol drift vs. the
build-reference's `fh`/`CZe`. Fast-path injects, JS validates,
idempotent re-run confirmed, duplicate-icon repro gone on Nobara
KDE Plasma 6 (Wayland) under Appearance → Colors / Plasma Style /
Global Theme.

Co-Authored-By: Claude <claude@anthropic.com>

* docs(readme): credit @IliyaBrook for tray duplicate-icon fix

Co-Authored-By: Claude <claude@anthropic.com>

---------

Co-authored-by: Claude <claude@anthropic.com>
Co-authored-by: aaddrick <aaddrick@gmail.com>
2026-04-27 09:19:36 -04:00
Andrej730
31c557acca build.sh: improve regexp quick window patch regexp readibility (#420)
* build.sh: improve regexp quick window patch regexp readibility

* docs(readme): credit @Andrej730 for quick-window regex readability

Co-Authored-By: Claude <claude@anthropic.com>

---------

Co-authored-by: aaddrick <aaddrick@gmail.com>
Co-authored-by: Claude <claude@anthropic.com>
2026-04-27 09:18:45 -04:00
Aaddrick
aecd25a519 docs(readme): replace cowork callout with APT migration advisory (#514)
Top-of-README callout swapped from the EXPERIMENTAL Cowork Mode
summary to a short pointer advisory for existing APT users whose
sources.list still targets aaddrick.github.io.

Rationale: the cowork block is accurate but describes routine
operational behavior; the migration advisory describes an imminent,
user-visible break on next `apt update` that needs action. The
detailed migration instructions live in the Installation section
(#510), so this callout is just a pointer, not duplication.

DNF users don't need to do anything (DNF follows the downgrade
silently); called out explicitly to avoid unnecessary sed-by-reflex.

Refs #493
2026-04-23 18:10:33 -04:00
Aaddrick
8bce730056 docs: point install instructions at pkg.claude-desktop-debian.dev (#510)
Phase 4a-APT cutover (#493, #503) moves binary distribution behind a
Cloudflare Worker at pkg.claude-desktop-debian.dev. The Worker serves
repo metadata directly and 302-redirects .deb/.rpm requests to GitHub
Release assets, which makes the >100 MB .deb push cap irrelevant.

GitHub Pages auto-301s legacy aaddrick.github.io/claude-desktop-debian
URLs to pkg.claude-desktop-debian.dev, but the redirect uses http://
(Pages has no cert for pkg.<domain> — DNS points at Cloudflare, so
Pages can never pass domain verification). apt refuses that scheme
downgrade as a security policy, so existing users' sources.list
silently breaks on the next `apt update`. DNF accepts the downgrade
and keeps working.

Changes:

- README.md: install snippets (APT + DNF) now point at
  pkg.claude-desktop-debian.dev directly. New users never touch the
  Pages redirect chain.
- README.md: add a "Migrating from the old aaddrick.github.io URL"
  section with sed one-liners for existing users + a short background
  paragraph explaining why the change was needed.
- .github/workflows/ci.yml: release-notes install snippets (APT + DNF,
  both branches) and the generated claude-desktop.repo file's baseurl
  and gpgkey all point at pkg.<domain>. Smoke-test chain walkers
  deliberately keep starting at github.io (they test the full 3-hop
  Pages→Worker→Releases chain for clients that do follow the
  downgrade, like curl-without-L and dnf).

Refs #493, #503
2026-04-23 16:12:05 -04:00
aaddrick
e11edf3475 docs: credit @RayCharlizard for ion-dist fix (#490)
Co-Authored-By: Claude <claude@anthropic.com>
2026-04-22 21:44:05 -04:00
aaddrick
ec51e39f86 docs: credit @aJV99 for Wayland GDK_BACKEND fix (#397)
Co-Authored-By: Claude <claude@anthropic.com>
2026-04-21 18:51:25 -04:00
Travis
a9719c93cc fix(cowork): forward CLAUDE_CODE_OAUTH_TOKEN to VM spawn env (#482) (#485)
* fix(cowork): forward CLAUDE_CODE_OAUTH_TOKEN to VM spawn env (#482)

buildSpawnEnv and BwrapBackend.spawn both stripped every CLAUDE_CODE_*
env var from the daemon's process.env via filterEnv(process.env,
['CLAUDE_CODE_']) -- including CLAUDE_CODE_OAUTH_TOKEN, the standard
auth channel for the in-VM claude binary. The bwrap sandbox mounts
home as an empty --dir, so ~/.claude/.credentials.json is inaccessible
inside; env is the only viable auth path. Result: every shell tool
call returned "Not logged in. Please run /login".

Upstream's seA() does include the token in the spawn env it assembles,
but on Linux that payload isn't reaching the daemon's params.env, so
the daemon's inherited process.env is the only surviving source.
Stripping it severed auth.

Introduce FORWARDED_ENV_KEYS = ['CLAUDE_CODE_OAUTH_TOKEN'] plus a
forwardAuthEnv helper that re-adds the token from process.env when
appEnv doesn't provide one. Extract buildBaseSpawnEnv as the shared
env-construction path for both spawn sites so the filter/forward logic
can't drift.

Diagnosis and reference diff by @pb3ck in #482. This PR extends the
fix to BwrapBackend.spawn (the second call site), factors the shared
helper, and adds regression coverage.

Co-Authored-By: Claude <claude@anthropic.com>

* refactor(cowork): fold forwardAuthEnv into buildBaseSpawnEnv

The forwardAuthEnv helper had a single call site inside
buildBaseSpawnEnv. Inlining the forward loop removes a layer of
indirection for a private helper and consolidates the empty-string
guard comment next to the code it documents.

No behavior change. All 72 tests in cowork-path-translation.bats
still pass, including the four #482 regression tests.

Co-Authored-By: Claude <claude@anthropic.com>

* docs(readme): credit @pb3ck for #482 diagnosis

Co-Authored-By: Claude <claude@anthropic.com>

---------

Co-authored-by: Claude <claude@anthropic.com>
2026-04-21 16:33:59 -05:00
Aaddrick
3344832b4e fix(launcher): disable GPU compositing on XRDP sessions (#475)
XRDP sessions lack GPU acceleration; Electron's default GPU compositing
renders a blank window. Detect XRDP via the $XRDP_SESSION env var and
systemd-logind's session Type, then append --disable-gpu and
--disable-software-rasterizer to the Electron args.

Based on @davidamacey's fix in #320, with the detection hardened: we
use `loginctl show-session -p Type --value` instead of probing for
xrdp-sesman, because that daemon runs on any host with xrdp installed
and would false-positive on local sessions.

Adds tests/launcher-xrdp-detection.bats with 8 cases covering both
positive and negative detection paths, including the XDG_SESSION_ID-
unset and loginctl-nonzero edge cases.

Fixes: #319

Co-authored-by: davidamacey <davidamacey@gmail.com>
Co-authored-by: Claude <claude@anthropic.com>
2026-04-21 08:26:21 -04:00
Aaddrick
b354353a36 feat(triage): Phase 0 scaffold for issue triage v2 (#456)
Directory scaffolding + skeleton workflow + issue templates. No live
behavior — v2 remains workflow_dispatch-only with `permissions: {}` and
a single job that echoes the issue number. v1 (`issue-triage.yml`) is
untouched.

Per docs/issue-triage/implementation-plan.md Phase 0:

- `.github/workflows/issue-triage-v2.yml` — skeleton workflow
- `.github/ISSUE_TEMPLATE/{config,bug_report,feature_request}.yml` —
  shapes input for the Stage 2 classifier and Stage 4 investigator;
  privacy disclosure in a non-editable markdown info block
- `.claude/scripts/prompts/.gitkeep` — prompts land per-phase
- `.claude/scripts/taxonomies/label-blocklist.json` — Stage 9 suggested-
  label gating (wontfix, invalid, duplicate, help wanted, good first
  issue); additional taxonomies land in Phase 4
- `.claude/scripts/reasons.json` — Stage 8b deferral-reason SSOT
  consumed by the renderer and post-processor (six entries)
- README Privacy section — keeps disclosure text discoverable without
  filing an issue; matches the templates' info block

Exit criteria: dispatch against any issue number prints correctly; no
API calls, no comments, no labels; `bug_report.yml` / `feature_request
.yml` render cleanly with the privacy block.

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-20 17:29:17 -04:00
Aaddrick
4cc6cc2183 Update sponsorship section in README.md
Removed sponsorship cost details and duplicate sponsorship link.
2026-04-19 02:34:00 -04:00
Travis
3c843244b3 fix: diagnose AppArmor userns block on bwrap probe (#351) (#434)
* fix: diagnose AppArmor userns block on bwrap probe (#351)

Ubuntu 24.04+ ships apparmor_restrict_unprivileged_userns=1 by
default, which blocks the user namespace bwrap needs to start. The
daemon's probe then fails, auto-detect silently falls through to
KVM, and KVM hangs waiting for a rootfs the user hasn't set up —
leaving Cowork stuck in a retry loop with no clear error.

- Classify the probe failure (classifyBwrapProbeError) so the daemon
  can distinguish AppArmor/userns blocks from generic failures and
  log a pointer to the TROUBLESHOOTING.md remediation.
- Stop falling through to KVM when bwrap is installed but blocked;
  drop to host-direct instead so users see a working (if unsandboxed)
  Cowork and the reason bwrap didn't engage. Users who actually want
  KVM can still set COWORK_VM_BACKEND=kvm.
- Mirror the probe + diagnosis in `--doctor` so misconfigured systems
  get the same actionable output without waiting for a daemon log.
- Document the AppArmor profile workaround in TROUBLESHOOTING.md.
- Credit @hfyeh for the diagnosis and profile snippet.

Co-Authored-By: Claude <claude@anthropic.com>

* refactor: simplify PR #434 per cdd-code-simplifier

Drop redundant `-n` guard around the COWORK_VM_BACKEND case in
`--doctor`: the `${VAR,,}` expansion is already safe on an unset var
(no `set -u` in this script) and the `kvm|host` arms simply don't
match an empty string.

Co-Authored-By: Claude <claude@anthropic.com>

---------

Co-authored-by: Claude <claude@anthropic.com>
2026-04-19 01:12:13 -05:00
Travis
e18a76facf fix: launcher-common.sh self-match and stale socket cleanup (#407) (#425)
* fix: launcher-common.sh self-match and stale socket cleanup (#407)

Three related bugs in scripts/launcher-common.sh that combine to break
Claude Desktop startup after any crash that reparents the cowork daemon
on Debian/Ubuntu/Mint systems.

1. cleanup_orphaned_cowork_daemon — the old pgrep pattern
   'claude-desktop' self-matches the launcher's own bash process
   (cmdline `bash /usr/bin/claude-desktop`), causing the function to
   return early on every invocation. The SIGTERM loop never runs.
   Replaced with `pgrep -f 'app\.asar'` plus $$/$PPID exclusion,
   --type= filter (skips chromium helpers), and /proc/*/status check
   (skips stopped/zombie launcher bashes). Added SIGKILL escalation
   after ~2s so cleanup_stale_cowork_socket reliably sees no daemon.

2. cleanup_stale_cowork_socket — the old implementation required
   socat (not preinstalled on Debian/Ubuntu/Mint) and fell through
   to a find -mmin +1440 check that ignored any socket younger
   than 24h. Rewritten to use the ordering invariant:
   cleanup_orphaned_cowork_daemon runs first and kills any orphan,
   so at this point an extant daemon proves the socket is live and
   an absent daemon proves the socket is stale. No socat dependency.

3. run_doctor orphan check — same self-match flaw as (1).
   claude-desktop --doctor reported [PASS] Cowork daemon: running
   (parent alive) on systems with a genuine orphan, actively
   misleading users trying to diagnose this failure. Applied the
   same detection primitive as (1).

Complements #410 (daemon-side crash recovery): #410 reduces how
often orphans are created; this ensures the launcher actually cleans
them up when they are.

Fixes #407

Co-Authored-By: martin152 <martin152@users.noreply.github.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* docs: credit martin152 in Acknowledgments for #407 launcher fix

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* style: quote RHS of $$/$PPID comparisons (SC2053)

Shellcheck SC2053: quote RHS in [[ ]] equality tests to prevent glob
matching. No behavior change — $$ and $PPID are always numeric PIDs.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: martin152 <martin152@users.noreply.github.com>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-18 19:28:22 -05:00
aaddrick
af8e393c8f docs: credit RayCharlizard for auto-memory path fix
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 15:44:41 -04:00
aaddrick
4bd913dd68 docs: credit sabiut for build artifact integration tests
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 15:23:10 -04:00
aaddrick
8690518bc1 docs: switch multi-item contributors to bulleted sublists
Update Acknowledgments section for readability — contributors with
multiple items now use nested bullet lists instead of inline commas.
Also adds cbonnissent's configurable bwrap mount points contribution.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 15:19:11 -04:00
aaddrick
a4fa9c8b24 docs: credit gianluca-peri for GNOME quit accessibility report
Co-Authored-By: Claude <claude@anthropic.com>
2026-04-01 07:05:18 -04:00
aaddrick
5926280d5c docs: credit jarrodcolburn for session-start hook sudo fix
Co-Authored-By: Claude <claude@anthropic.com>
2026-04-01 06:13:50 -04:00
aaddrick
5777727aa1 docs: credit reinthal for NixOS nodePackages fix
Co-Authored-By: Claude <claude@anthropic.com>
2026-04-01 04:42:27 -04:00
aaddrick
354f9706bc docs: credit jarrodcolburn for CI release pipeline analysis
Co-Authored-By: Claude <claude@anthropic.com>
2026-03-31 09:57:47 -04:00
aaddrick
1f03ca86a5 docs: credit typedrat for flake package scoping fix
Co-Authored-By: Claude <claude@anthropic.com>
2026-03-31 09:37:38 -04:00
aaddrick
0239cfd9e3 docs: credit aHk-coder and RayCharlizard for issue diagnostics
Co-Authored-By: Claude <claude@anthropic.com>
2026-03-25 06:50:00 -04:00
aaddrick
3741f64883 docs: update cowork notice to reflect KVM is non-functional
VM file downloads were disabled on Linux in #337, making the KVM
backend non-functional. Remove KVM from the backend table and add
a status note explaining why.

Co-Authored-By: Claude <claude@anthropic.com>
2026-03-23 07:01:23 -04:00
aaddrick
7a5aafe6f7 docs: credit cromagnone for confirming VM download loop on bwrap
Co-Authored-By: Claude <claude@anthropic.com>
2026-03-22 22:51:00 -04:00
aaddrick
3eb75b7008 docs: credit jarrodcolburn for virtiofsd PATH detection issue
Co-Authored-By: Claude <claude@anthropic.com>
2026-03-22 22:39:47 -04:00
aaddrick
11ec1e1d51 docs: credit CyPack for orphaned cowork daemon cleanup (#325)
Co-Authored-By: Claude <claude@anthropic.com>
2026-03-22 22:19:23 -04:00
aaddrick
3ada749410 feat: make bubblewrap the default cowork isolation backend
Swap auto-detection order from KVM → bwrap → host to
bwrap → KVM → host. KVM remains available via
COWORK_VM_BACKEND=kvm.

- detectBackend(): check bwrap before KVM
- --doctor: bwrap checked first; KVM deps shown as info
  (not warnings) unless COWORK_VM_BACKEND=kvm is set
- Fix header comment inaccuracy about rootfs.qcow2 check
- Update README and handover docs to reflect new default

Fixes #326

Co-Authored-By: Claude <claude@anthropic.com>
2026-03-21 18:33:00 -04:00
aaddrick
dee729b873 docs: update contributor credits for cbonnissent and arauhala
Co-Authored-By: Claude <claude@anthropic.com>
2026-03-20 11:51:16 -04:00
aaddrick
cb770de3df docs: add ecrevisseMiroir to contributors for bwrap sandbox isolation
Co-Authored-By: Claude <claude@anthropic.com>
2026-03-20 11:45:23 -04:00
aaddrick
1e2db5c0fe docs: update sabiut contributor credit for checksum validation
Co-Authored-By: Claude <claude@anthropic.com>
2026-03-20 08:47:33 -04:00
aaddrick
645ad92c49 docs: update jarrodcolburn contributor entry for gh-pages bloat fix
Co-Authored-By: Claude <claude@anthropic.com>
2026-03-19 08:28:14 -04:00
aaddrick
3f7a3c2328 fix: propagate run_doctor exit code in all launchers
All three launchers (deb, RPM, AppImage) used bare `exit` after
`run_doctor`, discarding the return code. Now uses `exit $?` so
non-zero exit codes from doctor diagnostics propagate correctly.

Also adds joekale-pp to README contributors for RPM doctor support.

Co-Authored-By: Claude <claude@anthropic.com>
2026-03-19 08:03:35 -04:00
aaddrick
9b4ac63323 fix: clean up CLAUDE_MENU_BAR boolean alias implementation
Follow-up to PR #299:
- Log original env var value instead of lowercased in alias resolution
- Use single quotes for literal string per style guide
- Document yes/no aliases in CONFIGURATION.md table
- Update noctuum's contributor entry for boolean alias work

Co-Authored-By: Claude <claude@anthropic.com>
2026-03-19 07:43:20 -04:00
aaddrick
2c62b79f0e docs: add cbonnissent to contributors for Cowork VM fix
Co-Authored-By: Claude <claude@anthropic.com>
2026-03-19 07:07:02 -04:00
aaddrick
27425236b6 docs: remove redundant NixOS flake reference from Acknowledgments
Co-Authored-By: Claude <claude@anthropic.com>
2026-02-28 21:31:59 -05:00
aaddrick
c9648275b8 chore: fix flake-lock workflow nits and add typedrat to contributors
- Pin DeterminateSystems/nix-installer-action to v21 instead of @main
- Use `nix flake update --flake .` to avoid deprecation warning
- Align github-actions[bot] email format with check-claude-version.yml
- Add typedrat to Acknowledgments for NixOS flake contribution (#266)

Co-Authored-By: Claude <claude@anthropic.com>
2026-02-28 21:30:28 -05:00
Aaddrick
b20b161b4e Merge pull request #266 from typedrat/feature/nixos-flake
feat: add NixOS flake with build.sh integration
2026-02-28 21:29:35 -05:00
Aaddrick
4929dde889 feat: KVM/bwrap isolation backends for cowork mode (#269)
* feat: add KVM/bwrap isolation backends for cowork mode

Refactor cowork-vm-service.js from monolithic VMManager into a pluggable
backend architecture with three isolation levels:

- HostBackend: direct execution on host (existing Phase 1 behavior)
- BwrapBackend: bubblewrap namespace sandbox (PID/mount isolation)
- KvmBackend: full QEMU/KVM VM with vsock, virtiofs, QMP monitor

Backend auto-detected at startup (KVM > bwrap > host) or overridden
via COWORK_VM_BACKEND env var. Shared helpers extracted for env
filtering, arg cleanup, command resolution, and work dir handling.

Also:
- Add Cowork Mode section to --doctor diagnostics with per-tool
  checks and distro-specific install hints
- Update Patch 4 to extract real win32 file entries for linux
  bundle manifest (enables app download infrastructure)
- Update handover documentation for Phase 2/3 architecture

Co-Authored-By: Claude <claude@anthropic.com>

* fix: correct KvmBackend vsock port, direction, and kernel cmdline

The guest sdk-daemon connects TO the host (CID=2), not the other way
around. Confirmed via disassembly of the guest binary: the vsock port
is 51234 (0xC822), matching the Hyper-V GUID in the Windows service.

- Change VSOCK_GUEST_PORT from 2222 to 51234
- Reverse socat bridge: VSOCK-LISTEN (host listens) instead of
  VSOCK-CONNECT (host connecting to guest)
- Add bridge server to accept persistent guest connection and route
  events/responses via callback map
- Fix kernel cmdline: root=LABEL=cloudimg-rootfs (matches fstab)

Co-Authored-By: Claude <claude@anthropic.com>

* fix: patch VM download to use disk-backed temp dir on Linux

Linux systems often mount /tmp as a small tmpfs (3-4GB). The VM
rootfs download decompresses to ~9GB, causing ENOSPC. Patch the
app's mkdtemp("wvm-") call to use the bundle directory (on real
disk) instead of os.tmpdir() on Linux.

Uses regex-based dynamic variable extraction to remain
version-agnostic across minified code changes.

Co-Authored-By: Claude <claude@anthropic.com>

* fix: handle stale cowork socket (ECONNREFUSED) on Linux

Stale sockets from previous sessions give ECONNREFUSED instead of
ENOENT, bypassing the retry loop and auto-launch entirely. Fix:

- Expand ENOENT check in retry loop to include ECONNREFUSED on Linux
- Add cleanup_stale_cowork_socket() to launcher scripts (all formats)
  that removes dead sockets before Electron starts
- Increase tmpdir patch search window from 1000 to 2000 chars

Co-Authored-By: Claude <claude@anthropic.com>

* fix: preserve DNS resolution inside bwrap sandbox

On systems using systemd-resolved, /etc/resolv.conf is a symlink to
/run/systemd/resolve/stub-resolv.conf. The bwrap --tmpfs /run option
wiped this out, breaking DNS resolution inside the sandbox and
preventing the spawned Claude process from reaching the API.

Bind-mount the resolved /run/systemd/resolve/ directory back into
the sandbox as read-only to restore DNS.

Co-Authored-By: Claude <claude@anthropic.com>

* fix: harden cowork isolation and build patches

- Remove broken _setupEventForwarding (events already flow through
  _handleGuestData); the second bridge connection was silently ignored
- Mount $HOME read-only in bwrap sandbox; only workDir and explicit
  mounts are writable (prevents writes to ~/.ssh, ~/.gnupg, etc.)
- Scope Patch 4 win32 extraction to actual win32:{} block via brace
  counting to avoid crossing into darwin/linux sections
- Set _qmpAvailable flag on QMP timeout instead of silently continuing
- Wrap CID allocation at 65535 to prevent unbounded growth
- Use execFileSync instead of execSync('which ...') in detectBackend
- Coerce response ID to String for Map lookup in _handleGuestData
- Use non-greedy [\s\S]*? in Patch 6 regex for nested brace robustness
- Update patch count threshold from 4 to 5 after adding Patch 8
- Add age-based fallback for stale socket cleanup when socat is missing
- Use indexOf-based splice in Patch 8 instead of string.replace()
- Extract shared resolveSdkBinary helper to deduplicate SDK resolution
- Remove dead retryFuncRe/retryFuncMatch variables from Patch 6

Co-Authored-By: Claude <claude@anthropic.com>

* fix: address security and correctness issues from code review

- Replace execSync string interpolation with execFileSync for qemu-img
  calls to eliminate shell injection risk
- Add path validation to readFile in both LocalBackend and KvmBackend
  to restrict reads to within the user's home directory
- Fix QMP _sendQmpCommand timer leak by clearing timeout on success
- Fix _pendingCallbacks.delete() to use String(msg.id) matching the
  String(msg.id) used in the .get() lookup
- Extract FORWARDED_EVENTS constant, cleanup helper, extractBlock
  helper, and consolidate doctor tool checks (from simplifier pass)

Co-Authored-By: Claude <claude@anthropic.com>

* docs: update README cowork notice with isolation backends and doctor info

Co-Authored-By: Claude <claude@anthropic.com>

---------

Co-authored-by: Claude <claude@anthropic.com>
2026-02-28 21:13:09 -05:00
Alexis Williams
d72f7915c5 docs: add NixOS flake installation instructions to README
Co-Authored-By: Claude <claude@anthropic.com>
2026-02-28 15:14:33 -08:00
aaddrick
a68acdca23 docs: add noctuum to contributor credits
Co-Authored-By: Claude <claude@anthropic.com>
2026-02-28 16:12:13 -05:00
aaddrick
a17e21d5e9 docs: add --doctor documentation to troubleshooting guide and README
Co-Authored-By: Claude <claude@anthropic.com>
2026-02-28 15:47:37 -05:00