1
How CoreDesktop Works
David Young edited this page 2026-10-26 16:01:09 -06:00

How CoreDesktop Works

CoreDesktop is a git repository of bash scripts. Each machine has a clone in ~/.local/share/coredesktop, and update keeps that clone current with git pull. Changes reach machines when they're pushed to main.

Repository layout

Path What's there
install.sh The installer. refresh re-runs it.
update, refresh, configure, version, sibling User commands. They're copied to ~/.local/bin by the installer and on every update.
utils.sh Shared helpers: install_packages, remove_packages, remove_flatpaks, enable_services, install_script, install_pipx_apps, ensure_gext, run_migrations
packages.conf Packages by category (SYSTEM_UTILS, DEV_TOOLS, MAINTENANCE, DESKTOP, MEDIA, FONTS), plus PIPX apps and SERVICES to enable
remove-packages.conf Packages and Flatpaks that update uninstalls
install-*.sh, claude.sh, bitwarden.sh Installer steps: Flatpaks, tmux plugins, mise/Ruby, Neovim, Claude Code, Bitwarden SSH agent
updates.d/ The steps update runs, in filename order. See Update Hooks.
migrations/ One-time changes for machines that are already installed. See Migrations.
configure.d/ The items configure offers. See Configure Items.
system/ Firewall, Snapper, system defaults, GPU drivers, update notifications
gnome/ GNOME extensions and their dconf settings
shell/ bashrc, aliases, functions and the starship prompt
sandbox/ The AI agent sandbox: the agent wrapper, bin/ links and default config/
skills/ Detailed guides for sibling project authors

Files on a machine

Path What it is
~/.local/share/coredesktop The clone
~/.local/bin/{update,refresh,configure,version,sibling} Installed copies of the commands
~/.local/state/coredesktop/migrations/ One empty file per migration that has run
~/.local/state/coredesktop/pacman-update.log Output of the last pacman -Su
~/.local/state/coredesktop/update-notified The newest version the user has been notified about
~/.config/coredesktop/core.conf What the user entered in configure core
~/.config/coredesktop/sandbox/ The user's own sandbox rules
~/.local/share/siblings/ Sibling projects

Install vs update

Getting a change onto every machine has two halves:

  • New machines run install.sh.
  • Existing machines only run update.
Kind of change New machines Existing machines
Add a package to packages.conf install.sh 10-pacman.sh installs new packages automatically
Remove a package Take it out of packages.conf Add it to remove-packages.conf
Add a service to SERVICES install.sh 15-services.sh enables it automatically
Add a pipx app to PIPX install.sh 60-pipx.sh installs it automatically
Anything else in install.sh install.sh Add a migration too
Something to redo on every update install.sh Add an update hook

If you change install.sh and existing machines need the change too, you must also add a migration.

Scripts that replace themselves

update pulls the repository, which can rewrite the scripts that are running. To make that safe:

  • update, refresh, configure, update-check and sandbox/agent wrap their whole body in { ...; exit; }, so bash reads the entire file before running any of it.
  • update installs its fresh copy to ~/.local/bin/update, then re-executes itself, so the rest of the run uses the new version.

Keep that wrapper in any new long-running script that lives in the repository.

Conventions

  • Bash, with a # Purpose : header on standalone scripts.
  • Scripts must be safe to run again. Users re-run the installer to repair things, and migrations can run on fresh installs.
  • Check before changing: is_installed, grep -q before appending, cmp -s before replacing a file.
  • Write per-machine state outside the repository (~/.config, ~/.local/state), never into tracked files, or git pull will fail.
  • Messages tell the user what happened and what to do next.