Files
coredesktop/.claude/skills/coredesktop-pop-merge/SKILL.md
T
davidandClaude Opus 5.5 d1108698bb
shellcheck / shellcheck (push) Failing after 14s
Add the plan for merging Pop!_OS support into configure
A Claude Code skill (/coredesktop-pop-merge) with the plan for folding
connector-popos, the Pop!_OS port of configure, back in here behind a
platform layer, so one Linux configure runs on Arch and Pop!_OS. It records
the facts verified while porting and the decisions still open, so the work
can be picked up later.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-11 14:42:30 -07:00

14 KiB
Raw Blame History

name, description
name description
coredesktop-pop-merge Plan and progress for merging Pop!_OS support (the connector-popos port) into CoreDesktop's configure, so one Linux configure runs on Arch and Pop!_OS with COSMIC. Use when resuming, continuing, checking the status of, or changing the Pop!_OS/CoreDesktop merge, the platform layer (configure.d/lib/platform.sh), or connector-popos.

Merge Pop!_OS support into CoreDesktop's configure

Where things stand

Work out the current state before doing anything; this plan was written on 2026-11-11 and may be partly done:

git -C ~/Projects/coredesktop fetch && git -C ~/Projects/coredesktop log --oneline origin/main -20
ls ~/Projects/coredesktop/configure.d/lib/platform.sh ~/Projects/coredesktop/pop 2>/dev/null
git -C ~/Projects/connector-popos log --oneline -5
curl -s -o /dev/null -A curl/8 -w '%{redirect_url}\n' https://federated.sh/pop

Map what you find onto the steps below, tell the user which step is next, and confirm before starting it.

Repositories

Repo Local What
Federated_Computer/coredesktop ~/Projects/coredesktop Arch + GNOME desktop setup; configure and configure.d/ are one part of it
Federated_Computer/connector-popos ~/Projects/connector-popos Standalone Pop!_OS port of configure, published 2026-11-11 (commit bc07e1d, MIT). To be archived after the merge.
Federated_Computer/connector-macos ~/Projects/connector-macos macOS port. Stays separate: bash 3.2, no jq/python, profiles, launchd, Seatbelt.

All on https://gitea.federated.computer. Pushing uses the cached git credentials. git's credential cache socket is blocked inside Claude Code's sandbox, so git push needs the sandbox turned off for that command.

Why merge

connector-popos is a fork, not a port. Measured against CoreDesktop: 10-core 92% unchanged, storage 93%, ai-servers 95%, sandbox item 97%, and goa-account, email-watch, setup-printers.sh, nextcloud.sh, mdns.sh and json.sh 94–100%. CoreDesktop's configure is changing fast (12+ commits since late October), so a fork drifts. That already happened twice: the step name clash (fixed in connector-macos, not CoreDesktop), and the Online Accounts 3.50 attention fix (only in connector-popos). macOS shares little code (10-core 37%, mdns 27%) and stays separate.

Facts verified while porting (don't re-derive)

  • Pop!_OS:
    • 24.04 LTS with COSMIC, released 2025-12-11; 26.04 was still unreleased in August 2026.
    • Pop's apt repo has cosmic-files 1.11.
    • pop-desktop/cosmic-session pull in gnome-keyring and libsecret, but not gnome-online-accounts or Evolution.
    • GOA, davfs2, restic, rclone and the rest come from Ubuntu noble.
  • COSMIC has no Online Accounts. The user chose GNOME Online Accounts + Evolution, with configure adding accounts through goa-account exactly as on Arch. Thunderbird was rejected, because the password-changed flow and the email watcher can't be ported to it.
  • GOA 3.50 (Ubuntu noble) works headless with goa-account: add, exists, pause/paused, update, check, remove and disabled all pass. But it sets AttentionNeeded (NotAuthorized) for unreachable servers too, for both Nextcloud and mail. So "needs attention" must not be read as "wrong password". The email watcher is already safe: it confirms with Nextcloud, and skips when Nextcloud can't be reached.
  • COSMIC session:
    • cosmic-session.target binds graphical-session.target and wants xdg-desktop-autostart.target, so user units with WantedBy=graphical-session.target and XDG autostart entries both work.
    • cosmic-notifications supports notify-send --action.
    • cosmic-term -e <cmd...> runs a command.
  • COSMIC Files sidebar:
    • cosmic-config ~/.config/cosmic/com.system76.CosmicFiles/v1/favorites, a RON list of Home|Documents|Downloads|Music|Pictures|Videos|Path("..")|Network(uri:,name:,path:)|Named(path:,name:).
    • Named exists since epoch 1.7.
    • If the file is missing, cosmic-files uses the six defaults, so write those first.
    • Helper: connector-popos/configure.d/lib/cosmic-favorites.
  • davfs2 on Ubuntu:
    • User mounts need mount.davfs setuid. Set it with echo "davfs2 davfs2/suid_file boolean true" | sudo debconf-set-selections, before install, or followed by dpkg-reconfigure -f noninteractive davfs2.
    • The group is davfs2; Arch uses network.
  • Ubuntu noble's versions: restic 0.16.4 and rclone 1.60.1, enough for rclone::webdav: and rclone obscure -. Pop's Node.js is too old for srt (needs 22.12+), so download the LTS from nodejs.org, checking SHASUMS256. Current Node (v26) needs libatomic1.
  • The sandbox on Ubuntu 24.04: bubblewrap may be blocked by kernel.apparmor_restrict_unprivileged_userns=1. The fix is an AppArmor profile for /usr/bin/bwrap with userns,. It's unverified whether Pop sets this; check on a real machine.
  • Package paths: Ubuntu's libnss-mdns uses mdns4_minimal, not mdns_minimal. GTK's CUPS backend is at /usr/lib/*/gtk-3.0/*/printbackends/libprintbackend-cups.so. fusermount3 is in /usr/bin. The keyring's SSH agent is at $XDG_RUNTIME_DIR/keyring/ssh, or gcr/ssh.
  • Installers: Tailscale's install.sh handles ID=pop. mise's apt repo is https://mise.jdx.dev/deb stable main, with the key at https://mise.jdx.dev/gpg-key.pub.
  • federated.sh is Caddy. Its /mac rule:
    • matches case-insensitively, with or without a trailing slash, ignoring the query; paths below it fall through
    • sends a User-Agent starting with Mozilla to the repo page, and everything else to the raw install.sh
    • /pop didn't exist on 2026-11-11 (it fell through to CoreDesktop's Arch installer); a Caddy skill to add it was handed to the server's agent, pointing at connector-popos

Decisions (defaults; the user can change them)

  1. Pop uses CoreDesktop's names: ~/.local/share/coredesktop, ~/.config/coredesktop, coredesktop-* units, coredesktop backup keyring attributes, /etc/coredesktop/smb. Arch users then need no migration. connector-popos used federated-connector-* names, so anyone who installed it needs a one-time migration, or a reinstall.
  2. Pop installs with git, cloning into ~/.local/share/coredesktop, so update is a git pull. This replaces connector-popos' tarball swap.
  3. Pop gets its own pop/update: pull, reinstall the commands, refresh the user units, restart the email watcher, and run migrations marked for Pop. CoreDesktop's update runs Arch-only hooks; Pop's own updater handles the system.
  4. Items install what's missing, with pkg_ensure. On Arch everything is there, so this does nothing.
  5. Hold the federated.sh/pop switch until step 6, or add a migration from connector-popos' paths.

Still open; ask the user:

  • Has CoreDesktop's owner signed off? The merge touches configure while it's being actively changed.
  • Branding on Pop: should users see "CoreDesktop" or "Federated Connector"?

Design: configure.d/lib/platform.sh

configure sources it; it sets PLATFORM=arch|pop from /etc/os-release. An Ubuntu-like system counts as pop, with a "made for Pop!_OS" warning. It provides:

  • pkg_installed, pkg_ensure <why> <pkg>... and pkg_install: pacman on Arch, dpkg/apt on Pop. They take Pop's (Debian) names, with a table of Arch names:

    Pop Arch
    avahi-utils avahi
    libsecret-tools libsecret
    libatomic1 gcc-libs
    python3-gi python-gobject
    gir1.2-secret-1 libsecret
    libnotify-bin libnotify
    smbclient smbclient
  • flatpak_installed and flatpak_ensure.

  • sidebar_add, sidebar_remove and sidebar_has. Both platforms write GTK bookmarks; Pop also writes COSMIC Files' favorites.

  • DAVFS_GROUP (network or davfs2) and davfs2_ready (setuid through debconf on Pop; nothing on Arch).

  • element_installed and element_config: the im.riot.Riot Flatpak keeps it at ~/.var/app/im.riot.Riot/config/Element/config.json, otherwise ~/.config/Element/config.json.

  • goa_ready and the accounts text: "Online Accounts (Settings)" on Arch, "shown in Evolution" on Pop, which also installs gnome-online-accounts, evolution, python3-gi and gir1.2-secret-1.

  • install_tailscale: pacman, or Tailscale's install.sh, downloaded then run.

  • install_mise and mise_activated: on Arch, mise comes from pacman and shell/bashrc activates it; on Pop, mise's apt repo and a block in ~/.bashrc.

Done in place, not through the layer:

  • system/run-in-terminal tries cosmic-term -e first.
  • system/sftp-mount also tries keyring/ssh.
  • setup-printers.sh checks dependencies and GTK's backend per platform, and accepts mdns4_minimal.

Steps (one reviewable PR each)

1. Platform layer, Arch unchanged (pure refactor)

  • Add platform.sh with the Arch side only.
  • Change 10-core.sh, 15-tailscale.sh, 20-backup.sh, 40-languages.sh, 60-storage.sh (sudo pacman -S sshfs becomes pkg_ensure) and setup-printers.sh to call it.
  • Drop the is_installed checks that only hid an item when its tools were missing (backup, ai-servers, printers, storage, tailscale); the item now offers to install them.
  • Tests:
    • bats tests for platform.sh, stubbing pacman, dpkg and apt as tests/test_helper.bash already does
    • make lint, bats tests
    • CoreDesktop's VM smoketest quick tier (coredesktop-dev smoketest run, through the coredesktop-dev sibling), to show Arch is unchanged

2. Fixes for both platforms

  • test_account in 10-core.sh:
    • drop the "$GOA_ACCOUNT" attention branch
    • keep email-watch --check-password (Nextcloud) before goa-account check
    • update the comment: 3.50 flags unreachable servers. On Arch's 3.58 this only adds one Nextcloud sign-in during Test a Core.
  • Rename step to core_step in 10-core.sh, including the [ ... ] && step element|tally lines.
  • Comment fixes: the 3.58 notes in configure.d/lib/goa-account and system/email-watch.

3. Pop's side of the layer

  • Fill in platform.sh for Pop.
  • Copy from connector-popos:
    • configure.d/lib/cosmic-favorites
    • the davfs2 setuid step
    • the Tailscale and mise apt-repo installs
    • the Element Flatpak path
  • configure: a menu title and the not-Pop warning per platform; refuse to run as root.
  • Docs: what's different on Pop (Evolution, COSMIC Files, AppArmor) and what needs a real Pop machine.
  • connector-popos' README "Differences from CoreDesktop" lists everything this step must cover.

4. The agents item, sharing the sandbox setup

  • Move sandbox/setup.sh's logic into functions in sandbox/lib.sh, used by both setup.sh (Arch, updates.d/72-sandbox.sh) and a new configure.d/30-agents.sh (from connector-popos/configure.d/30-agents.sh):
    • Claude Code's sandbox defaults, plus claude.sh's notification hooks
    • the Hermes gateway drop-in (keep the name coredesktop-sandbox.conf)
    • the Cline Desktop entry
  • Renumber 30-claude, 31-opencode and 32-hermes to 31, 32 and 33. Item names don't change.
  • 30-agents on Arch: shows done.
  • 30-agents on Pop: installs the agents with their own installers, installs Node.js and srt under ~/.local/share/coredesktop/tools (lib/tools.sh), adds libatomic1, the PATH block and the AppArmor offer.
  • srt_path finds ~/.local/bin/srt (Arch's npm install) or the tools one. sandbox/agent uses agent_path (connector-popos configure.d/lib/agents.sh).
  • sandbox/config/base.json: add ubuntu.com, *.ubuntu.com, pop-os.org, *.pop-os.org, system76.com and *.system76.com next to Arch's, and ~/.config/evolution, ~/.local/share/evolution, ~/.cache/evolution, ~/.config/goa-1.0 and ~/.thunderbird to denyRead.

5. Installing and updating on Pop

  • pop/install.sh: adapt from connector-popos/install.sh.
    • preflight: apt, not root, sudo group, network
    • apt install git curl jq libsecret-tools python3-gi gir1.2-secret-1 libnotify-bin
    • clone, install_script for configure and pop/update into ~/.local/bin
    • put ~/.local/bin on PATH at the top of ~/.bashrc
    • mark the existing migrations as done
    • offer configure, reading answers from /dev/tty and apt's stdin from /dev/null
  • pop/update: git pull --ff-only, reinstall the commands, refresh the coredesktop-* units configure installed, restart the email watcher, run Pop migrations.
  • Migrations: run_migrations (utils.sh) runs only those whose header has # platforms: naming the current platform; unmarked ones are Arch only. Check it doesn't pull in Arch-only parts of utils.sh; if it does, move it to lib/migrations.sh.
  • Tests: move connector-popos/smoketest/ to smoketest/pop/, rename the paths and units, and add it and bats tests to .gitea/workflows (the runner is ubuntu-latest).

6. Switch over

  • After a manual pass on a real Pop!_OS 24.04 machine (below), point federated.sh/pop at https://gitea.federated.computer/Federated_Computer/coredesktop/raw/branch/main/pop/install.sh, with the browser redirect going to the repo page. That's a change to the Caddy skill's two targets.
  • Archive connector-popos, with a README pointer.

Verification

  • make lint and bats tests on every PR.
  • The Arch VM smoketest after steps 1, 2 and 4.
  • The Pop Docker smoketest (smoketest/pop/run --tier all) after steps 3–5. Docker needs the sandbox turned off for that command. Its scenarios:
    • install and update
    • the menu
    • GOA 3.50
    • Superpanel, Element, the sidebar, davfs2's secret
    • restic and rclone against a local rclone serve webdav
    • the srt sandbox, --privileged
    • davfs2 setuid, sshfs, GTK print backend, mise
  • Manual, on real Pop!_OS, which containers can't check:
    • COSMIC Files showing the sidebar entries
    • Evolution against a real Core
    • the davfs2 mount after logging out and in
    • the backup timer and the email watcher's notification, which opens configure core in COSMIC Terminal
    • Tailscale with a Core's headscale
    • real SMB and SFTP mounts
    • whether the AppArmor profile is needed

Risks

  • Arch regressions: step 1 changes no behavior and is checked on the VM first.
  • Collisions with ongoing configure work: land steps 1–2 quickly, and tell contributors that new item code should go through platform.sh.
  • update means different commands on Arch and Pop. Document both.

Effort

About 1.5–2 days:

  • steps 1–2: half a day
  • steps 3–4: half a day to a day
  • step 5: half a day
  • step 6 and the manual pass: an hour or two, plus a Pop machine