| Siblings |
Sibling projects are git repositories that build on Federated CoreDesktop. Install them with one command, keep them current with update, browse the directory, and learn how to format and submit your own. |
| type |
compact |
eyebrow |
title |
subhead |
ctas |
logTitle |
log |
| hero |
true |
sibling · sibling add · sibling list · sibling remove |
Build your own layer on top. |
A sibling project is a git repository that builds on CoreDesktop. Install one with a single command, and every `update` keeps it current along with everything else. |
| label |
url |
style |
| Browse siblings |
#directory |
primary |
|
| label |
url |
style |
| Make your own |
#format |
ghost |
|
|
~ $ sibling add https://gitea.example.com/someone/my-tools.git |
| tag |
text |
| Clone |
my-tools into ~/.local/share/siblings/my-tools |
|
| tag |
text |
| install |
Running install.sh from the repo folder |
|
| tag |
text |
| pacman |
Installing jq and ripgrep |
|
| tag |
text |
| Bin |
Installed ~/.local/bin/my-tools |
|
| done |
text |
| true |
my-tools installed. update keeps it current. |
|
|
|
| type |
kicker |
headline |
body |
| text |
What's a sibling? |
Your tools, updated with CoreDesktop. |
CoreDesktop covers what most people need. A sibling covers the rest: your team's tools, your dotfiles, the extra apps your work depends on. It's an ordinary git repository with two optional scripts at its top level, `install.sh` and `update.sh`.
`sibling` clones the repository into `~/.local/share/siblings/` and runs its `install.sh` once. After that, every `update` pulls the latest version of each sibling and runs its `update.sh`, so the people using your project get your changes without doing anything.
A repository needs no special files to be installable. Without the scripts, `update` just keeps the clone up to date.
|
|
| type |
id |
kicker |
headline |
lede |
command |
note |
| command |
install-a-sibling |
Install one |
One command to add a sibling. |
It asks for the repository's git URL, clones it, runs its install.sh (if it has one), and confirms the install. |
sibling |
Any URL or path `git clone` accepts will do. Private repositories work too, as long as you can already clone them (SSH key, credential helper or password), and every later `update` needs the same access. |
|
| type |
kicker |
headline |
headers |
rows |
| table |
Commands |
Everything sibling does. |
|
| `sibling` |
| Asks for a git URL, then installs that project |
|
| `sibling add <url>` |
| The same, without the prompt. Run it again to repair an install |
|
| `sibling list` |
| Shows the installed siblings, their URLs and current commits |
|
| `sibling remove <name>` |
| Deletes `~/.local/share/siblings/<name>`. Anything its install.sh set up elsewhere stays |
|
|
|
| type |
id |
kicker |
headline |
lede |
emptyText |
emptyCtas |
| siblings |
directory |
Directory |
Sibling projects. |
Projects that build on CoreDesktop. Copy a command into a terminal to install one. |
**No sibling projects are listed yet.** Built something on CoreDesktop? Yours could be the first. |
| label |
url |
style |
| Submit your project |
#submit |
primary |
|
| label |
url |
style |
| How to format it |
#format |
text |
|
|
|
| type |
id |
kicker |
headline |
lede |
items |
| steps |
format |
Make your own |
Turn a repository into a sibling. |
Both scripts are optional, and both go at the top level of the repository. Other names or locations are ignored. |
| title |
body |
| Add install.sh |
Runs once, when someone runs `sibling add`, and again if they re-run it. Use it for one-time setup: prompts, accounts, initial config. |
|
| title |
body |
| Add update.sh |
Runs on every `update`, right after the repository has been pulled. Use it to apply what changed since the last update. |
|
| title |
body |
| Tell people how to install it |
In your README, tell users to install with `sibling add <url>`. Then [submit it](#submit) to the directory. |
|
|
|
| type |
kicker |
headline |
lede |
columns |
| split |
The rules |
What each script should do. |
Both run with `bash`, from the repository folder, so they don't need to be executable. A `#!/bin/bash` line keeps them runnable by hand. |
| title |
items |
| install.sh |
| **Exit non-zero on failure.** `set -e` near the top is the simplest way. `sibling` then tells the user it failed and how to retry. |
| **Make it safe to re-run.** Re-running `sibling add` is how users repair an install, so skip work that's already done instead of failing on it. |
| It may prompt the user, since it runs in their terminal. |
| Install commands into `~/.local/bin` (already on `PATH`) with `install_script`. |
|
|
| title |
items |
| update.sh |
| **Make it idempotent.** It runs on every `update`, usually with nothing to do. |
| **Don't prompt.** Users expect `update` to run through without questions, apart from `sudo` passwords. |
| **Exit non-zero only for real failures**, so that `update`'s error summary stays meaningful. |
| **Print what it's doing.** CoreDesktop prints only the project's name before it runs. |
| It's fine to leave it out if pulling the repository is enough, for example when `~/.local/bin` holds symlinks into the repo. |
|
|
|
|
| type |
kicker |
headline |
items |
| features |
Good to know |
The environment your scripts run in. |
| label |
body |
| Nothing is inherited |
Each script runs as its own `bash` process, with no variables or functions from CoreDesktop. `$COREDESKTOP` is not set, so set it yourself: `COREDESKTOP="$HOME/.local/share/coredesktop"`. |
|
| label |
body |
| Find your own files |
Locate files relative to the script, not a hard-coded path. People may clone the repository somewhere else and run install.sh by hand. |
|
| label |
body |
| Keep pulls working |
`update` pulls with `--ff-only` and never merges or resets. Never force-push the default branch, and never write into tracked files: put generated files and per-machine state in `~/.config/<name>/` or in paths listed in `.gitignore`. |
|
| label |
body |
| sudo works as normal |
`sudo` prompts for a password as usual. CoreDesktop doesn't give siblings passwordless sudo. |
|
|
|
| type |
kicker |
headline |
lede |
headers |
rows |
| table |
Helpers |
CoreDesktop's helpers, from utils.sh. |
Source `$COREDESKTOP/utils.sh` to use them. |
|
| `install_packages ...` |
| Installs pacman and AUR packages with yay, skipping installed ones |
|
| `remove_packages ...` |
| Removes installed pacman and AUR packages |
|
| `remove_flatpaks ...` |
| Uninstalls Flatpaks that are installed |
|
| `enable_services ...` |
| Enables systemd services not yet enabled |
|
| `install_script src dst` |
| Copies a file atomically and makes it executable |
|
| `is_installed pkg` |
| True if a pacman package is installed |
|
|
|
| type |
id |
kicker |
headline |
body |
| text |
templates |
Templates |
Start from these. |
Share the install logic between the two scripts, so packages or commands you add later reach existing machines through `update`, not just new installs.
**install.sh**
```
#!/bin/bash
#
# Purpose : Install <project> (run by CoreDesktop's `sibling add`)
set -e
SELF="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
COREDESKTOP="$HOME/.local/share/coredesktop"
source "$COREDESKTOP/utils.sh"
# One-time setup: prompts, accounts, initial config...
mkdir -p "$HOME/.config/<project>"
# Everything that update.sh also needs to keep current
bash "$SELF/update.sh"
echo "<project> installed."
```
**update.sh**
```
#!/bin/bash
#
# Purpose : Keep <project> current (run by CoreDesktop's `update`)
set -e
SELF="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
COREDESKTOP="$HOME/.local/share/coredesktop"
source "$COREDESKTOP/utils.sh"
PACKAGES=(
jq
ripgrep
)
install_packages "${PACKAGES[@]}"
mkdir -p "$HOME/.local/bin"
install_script "$SELF/bin/<project>" "$HOME/.local/bin/<project>"
```
|
|
| type |
id |
kicker |
headline |
body |
| text |
testing |
Testing |
Try it in a throwaway home folder. |
Point `sibling` at a local clone, with a temporary `HOME` so nothing touches your real one:
```
export HOME="$(mktemp -d)"
mkdir -p "$HOME/.local/share"
ln -s /path/to/real/coredesktop "$HOME/.local/share/coredesktop"
# Install
bash "$HOME/.local/share/coredesktop/sibling" add /path/to/sibling-repo
# Commit a change in /path/to/sibling-repo, then run the update hook the way update does
( source "$HOME/.local/share/coredesktop/updates.d/71-siblings.sh"; is_installed && run_update )
# Re-run the install to check it's safe to repeat
bash "$HOME/.local/share/coredesktop/sibling" add /path/to/sibling-repo
```
Scripts that call `sudo`, `yay` or `systemctl` still change the real system, even with a temporary `HOME`. Test those on a machine or VM you don't mind changing.
|
|
| type |
id |
kicker |
headline |
body |
| text |
custom-hooks |
Advanced |
Full control with an update hook. |
Instead of `update.sh`, a project can install its own hook into CoreDesktop's `updates.d/`, which `update` runs in filename order. Use one approach or the other, not both, or the project updates twice.
Name the hook with an unused number from **72 to 79**, so it runs after CoreDesktop's own updates but before its end-of-run steps (80 and up), and copy it in from your install.sh:
```
cp updates.d/72-myproject.sh ~/.local/share/coredesktop/updates.d/
```
A hook can define `run_update`, and optionally `is_installed`, so it's skipped on machines where the project isn't installed. The full guide is in [sibling-project-updates.md](https://gitea.federated.computer/Federated_Computer/coredesktop/src/branch/main/skills/sibling-project-updates.md).
|
|
| type |
kicker |
headline |
items |
| checklist |
Checklist |
Before you share it. |
| The repository can be cloned by URL by the people who will install it. |
| `install.sh` (optional) is at the top level, exits non-zero on failure, and is safe to re-run. |
| `update.sh` (optional) is at the top level, idempotent, doesn't prompt, and prints what it's doing. |
| Scripts find their own files relative to the script and set `COREDESKTOP="$HOME/.local/share/coredesktop"` themselves. |
| Nothing writes to tracked files in the clone, and the default branch is never force-pushed. |
| The project doesn't also copy a hook into CoreDesktop's `updates.d/`. |
| The README tells users to install with `sibling add <url>`. |
|
|
| type |
id |
kicker |
headline |
lede |
items |
ctas |
| steps |
submit |
Submit |
Get your project in the directory. |
Built a sibling other people could use? Tell us about it, and we'll add it to the directory. |
| title |
body |
| Check it |
Go through the [checklist](#checklist). The repository must be public, so anyone can install it with `sibling add`, and should have a license. |
|
| title |
body |
| Open an issue |
Open an issue on the CoreDesktop repository titled **Sibling: your project's name**, with its git URL, a one-line description, and your name or handle. |
|
| title |
body |
| We'll take a look |
We'll install it on a test machine, and once it works, add it to the directory. We'll reply on the issue either way. |
|
|
|
|
| type |
headline |
body |
ctas |
| final-cta |
Need CoreDesktop itself changed? |
If what you're building would be useful to everyone, it might belong in CoreDesktop instead of a sibling. |
| label |
url |
style |
| Contribute to CoreDesktop |
/contribute/ |
primary |
|
|
|
|