Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 13 additions & 6 deletions .agents/skills/add-package/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -87,14 +87,21 @@ Apply these rules in order:
`.agents/skills/add-package/pkg-lookup flatpak` result's `name` field).
- If only an AppImage exists from a GitHub release: set
`appimage: <owner>/<repo>` and verify with `.agents/skills/add-package/pkg-lookup appimage`.
6. **Requires a Homebrew tap**: set `brew_tap: "<tap>"` (e.g., `BarutSRB/tap`).
6. **CLI tool for mise profiles (devpod-slim)**: if the tool publishes prebuilt
Linux release binaries, set `mise: "aqua:<owner>/<repo>"` (check with
`mise registry <name>`; fall back to `github:<owner>/<repo>`), then run
`scripts/mise-lock` and commit the updated `home/.chezmoitemplates/mise-packages.lock`.
Devpods have glibc 2.36: if the release has a musl build, add
`mise_opts: { matching: "musl" }`; otherwise hold a working version with
`mise_version`.
7. **Requires a Homebrew tap**: set `brew_tap: "<tap>"` (e.g., `BarutSRB/tap`).
See `omniwm` in the repo for the pattern.
7. **AUR-only Arch package**: set `pacman: <aur-name>` if the AUR name differs
8. **AUR-only Arch package**: set `pacman: <aur-name>` if the AUR name differs
from the YAML key. Paru handles both repos.

After applying these rules, you should have a minimal entry — only fields that
differ from defaults. Read the schema comments at
`home/.chezmoidata/packages.yaml:9-39` if uncertain about defaults.
`home/.chezmoidata/packages.yaml:9-42` if uncertain about defaults.

### 4. Confirm tags and description

Expand Down Expand Up @@ -145,14 +152,14 @@ Default to **No** — let them apply on their schedule.

## Schema cheatsheet

Authoritative source: `home/.chezmoidata/packages.yaml:9-39` (header comment).
Authoritative source: `home/.chezmoidata/packages.yaml:9-42` (header comment).

- Cascade order: `brew → brew_cask → pacman → apt → dnf → rpm_ostree → flatpak → appimage`.
- Cascade order: `mise → brew → brew_cask → pacman → apt → dnf → rpm_ostree → flatpak → appimage`.
- Tri-state fields (`brew`, `pacman`, `apt`, `dnf`): **absent** = use YAML key,
**string** = override, **false** = exclude from this manager.
- Modifiers: `brew_cask: true` flips to cask on macOS; `brew_tap: "<tap>"`
preinstalls a tap.
- Opt-in: `rpm_ostree`, `flatpak`, `mas`, `appimage` are only used when the
- Opt-in: `mise`, `rpm_ostree`, `flatpak`, `mas`, `appimage` are only used when the
field is present AND truthy.
- Required fields: `tags`, `desc`.

Expand Down
79 changes: 76 additions & 3 deletions .github/workflows/devpod-linuxbrew-cache.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ name: Build devpod linuxbrew cache
#
# The build runs the full `chezmoi apply` for profile=devpod, so any chezmoi
# template, package, or run_* script regression also fails this workflow.
# Pull requests build and verify the PR branch (devpod and devpod-slim) but
# never publish; only main publishes the release asset.

on:
schedule:
Expand All @@ -20,6 +22,13 @@ on:
- 'install.sh'
- 'scripts/**'
- '.github/workflows/devpod-linuxbrew-cache.yml'
pull_request:
paths:
- '.chezmoiroot'
- 'home/**'
- 'install.sh'
- 'scripts/**'
- '.github/workflows/devpod-linuxbrew-cache.yml'

permissions:
contents: write
Expand All @@ -28,10 +37,14 @@ env:
PLATFORM: debian12-x86_64
RELEASE_TAG: linuxbrew-cache-debian12-x86_64
ARCHIVE: linuxbrew-debian12-x86_64.tar.zst
# Branch under test: the PR head for pull requests, else the pushed/dispatched ref.
DOTFILES_REF: ${{ github.head_ref || github.ref_name }}
Comment thread
coderabbitai[bot] marked this conversation as resolved.

jobs:
build:
name: Build linuxbrew tarball (debian:12)
# Fork PRs: their branch lives in the fork, which install.sh can't clone.
if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository
runs-on: ubuntu-latest
container:
image: debian:12
Expand Down Expand Up @@ -68,7 +81,8 @@ jobs:
set -eux
sudo -u builder -H \
SKIP_LINUXBREW_FETCH=1 \
bash -lc 'cd ~ && curl -fsSL https://raw.githubusercontent.com/tyvsmith/dotfiles/main/install.sh | bash -s -- --profile devpod'
DOTFILES_REF="$DOTFILES_REF" \
bash -lc 'cd ~ && curl -fsSL "https://raw.githubusercontent.com/tyvsmith/dotfiles/$DOTFILES_REF/install.sh" | bash -s -- --profile devpod --branch "$DOTFILES_REF"'

- name: Verify brew is usable
run: |
Expand All @@ -85,10 +99,24 @@ jobs:
set -eux
sudo -u builder -H bash -lc "
cd \$HOME
# Runtime-only tree: drop translations, headers, static libs, and
# doc/info pages (keep man pages, which fish also uses for
# completions), plus the prefix symlinks that point at them.
tar --use-compress-program='zstd -T0 -10' \
--exclude='.linuxbrew/Caskroom' \
--exclude='.linuxbrew/var/homebrew/locks' \
--exclude='.linuxbrew/Library/Logs' \
--exclude='.linuxbrew/Cellar/*/*/share/locale' \
--exclude='.linuxbrew/Cellar/*/*/share/doc' \
--exclude='.linuxbrew/Cellar/*/*/share/info' \
--exclude='.linuxbrew/Cellar/*/*/share/gtk-doc' \
--exclude='.linuxbrew/Cellar/*/*/include' \
--exclude='.linuxbrew/share/locale' \
--exclude='.linuxbrew/share/doc' \
--exclude='.linuxbrew/share/info' \
--exclude='.linuxbrew/share/gtk-doc' \
--exclude='.linuxbrew/include' \
--exclude='.linuxbrew/*.a' \
-cf /tmp/${ARCHIVE} \
.linuxbrew
ls -lh /tmp/${ARCHIVE}
Expand Down Expand Up @@ -130,10 +158,55 @@ jobs:
retention-days: 7
if-no-files-found: error

devpod-slim:
name: Verify devpod-slim apply (debian:12)
# Fork PRs: their branch lives in the fork, which install.sh can't clone.
if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository
runs-on: ubuntu-latest
container:
image: debian:12
options: --user root
steps:
- name: Install container prerequisites
run: |
set -eux
export DEBIAN_FRONTEND=noninteractive
apt-get update -qq
apt-get install -y --no-install-recommends curl ca-certificates git sudo procps file locales
locale-gen en_US.UTF-8 || true
useradd -m -s /bin/bash builder
echo 'builder ALL=(ALL) NOPASSWD: ALL' > /etc/sudoers.d/builder
chmod 0440 /etc/sudoers.d/builder

- name: Apply dotfiles via install.sh (profile=devpod-slim)
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
set -eux
sudo -u builder -H DOTFILES_REF="$DOTFILES_REF" MISE_GITHUB_TOKEN="$GITHUB_TOKEN" \
bash -lc 'cd ~ && curl -fsSL "https://raw.githubusercontent.com/tyvsmith/dotfiles/$DOTFILES_REF/install.sh" | bash -s -- --profile devpod-slim --branch "$DOTFILES_REF"'

- name: Verify managed tools run
run: |
set -eux
sudo -u builder -H bash -lc '
cd ~
tools=$(sed -n "s/^\"\([^\"]*\)\" = .*/\1/p" ~/.config/mise/conf.d/20-packages.toml)
broken=0
for d in $(~/.local/bin/mise bin-paths $tools); do
for f in "$d"/*; do
[ -f "$f" ] && [ -x "$f" ] || continue
if ldd "$f" 2>&1 | grep -q "not found"; then echo "BROKEN: $f"; broken=1; fi
done
done
~/.local/bin/fish -c "rg --version; atuin --version; tmux -V; nvim --version | head -1"
exit $broken
'

publish:
name: Publish to GitHub Release
needs: build
if: github.event_name != 'pull_request'
needs: [build, devpod-slim]
if: github.event_name != 'pull_request' && github.ref == 'refs/heads/main'
runs-on: ubuntu-latest
permissions:
contents: write
Expand Down
17 changes: 15 additions & 2 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,8 @@ DOTFILES_PROFILE=arch-desktop chezmoi init

Each profile (defined in `home/.chezmoidata/profiles.yaml`) fully specifies:
- **`tags`**: comma-delimited category tags (`core`, `core-extra`, `container`, `dev`, `dev-extra`, `dev-toolchains`, `ai`, `experiment`, `hardware`, `ui`, `ui-extra`, `gaming`)
- **Package managers**: `brew`, `pacman`, `apt`, `dnf`, `rpm_ostree`, `flatpak`
- **Package managers**: `mise`, `brew`, `pacman`, `apt`, `dnf`, `rpm_ostree`, `flatpak`
- **`devpod`**: Uber devpod — runs the devpod bootstrap and login-shell scripts
- **`work`**: work machine (system SSH agent, corporate configs)
- **`decrypt`**: enable age decryption of private configs
- **`backup`**: personal machine — install the restic stack and schedule backups (default off; servers/containers/Macs stay off, Macs use Time Machine)
Expand All @@ -65,6 +66,7 @@ If no profile is specified, auto-detects from distro (macOS → `macos-work`, Ar
| `arch-desktop` | core, core-extra, container, dev, dev-extra, dev-toolchains, experiment, ai, hardware, ui, ui-extra, gaming | pacman, flatpak, appimage | | yes | yes | Arch Linux desktop |
| `debian-server` | core | apt | | | | Debian/Ubuntu server — CLI only |
| `devpod` | core, dev, ai | brew | yes | no | | Work devpod — lean; toolchains from image/repo |
| `devpod-slim` | core, dev, ai | mise | yes | no | | Work devpod — same tools as pinned mise binaries, no Linuxbrew |
| `silverblue` | core, core-extra, container, dev, dev-extra, dev-toolchains, experiment, ai, hardware, ui, ui-extra, gaming | brew, rpm_ostree, flatpak, appimage | | yes | | Silverblue/Bazzite immutable |

**Package categories:**
Expand Down Expand Up @@ -103,11 +105,21 @@ Brew modifier fields:
- `brew_tap:` — Homebrew tap required before install

Opt-in manager fields are present when available:
- `mise:` — mise backend spec (`aqua:owner/repo` preferred, `github:owner/repo` when aqua lacks it); installs a prebuilt release binary
- `rpm_ostree:` — rpm-ostree package (`true` = use YAML key, string = override name; for immutable Fedora)
- `flatpak:` — Flatpak app ID
- `appimage:` — GitHub repo (`owner/name`) for AppImage download

Cascade order: `brew → brew_cask → pacman → apt → dnf → rpm_ostree → flatpak → appimage`. Each package goes to the first enabled manager that can handle it, determined at template time by `home/.chezmoitemplates/cascade-filter`. Each manager has its own `run_onchange_*` script with a profile guard that renders to `exit 0` when the manager is not enabled.
Cascade order: `mise → brew → brew_cask → pacman → apt → dnf → rpm_ostree → flatpak → appimage`. Each package goes to the first enabled manager that can handle it, determined at template time by `home/.chezmoitemplates/cascade-filter`. Each manager has its own `run_onchange_*` script with a profile guard that renders to `exit 0` when the manager is not enabled.

**mise packages (`devpod-slim`):**
Profiles with `mise: true` install every package that declares a `mise:` backend as a prebuilt release binary, with no Linuxbrew. `home/dot_config/mise/conf.d/20-packages.toml.tmpl` renders them at `"latest"`; `home/.chezmoitemplates/mise-packages.lock` (committed, generated) pins each to an exact version, URL, and sha256 per platform. chezmoi merges those pins into the machine's own `~/.config/mise/mise.lock` (`home/dot_config/mise/modify_mise.lock`): it adds missing tools and takes newer repo pins, keeps versions upgraded locally, and never touches or removes entries it does not manage (toolchains, `mise use -g`). The install script runs `mise install --locked` on the managed tools. Packages without a `mise:` field (git, wget, tree, socat) come from the devpod image.

- Add or remove a package: edit `packages.yaml`, run `scripts/mise-lock`, commit both files.
- Upgrade: `scripts/mise-lock --bump`, review the lockfile diff, commit. Machines update on the next apply.
- Local mise use is safe: `mise use -g`, toolchains, and `mise upgrade` write the same lockfile, and the merge keeps their entries.
- Devpods run Debian 12 (glibc 2.36). Some upstream gnu builds need newer glibc: pick a static build with `mise_opts: { matching: "musl" }` or hold a version line with `mise_version`. The install script warns about any managed binary `ldd` cannot resolve.
- Reset a machine's lockfile to exactly the repo's (drops stale entries, including local-only pins): `scripts/mise-lock --force-overwrite` on that machine.

**Debian/Ubuntu apt availability:**
The apt install script uses runtime `apt-cache` checks to determine package availability, so it works correctly across different Debian/Ubuntu versions without static exclusion lists. Packages available in Ubuntu 24.04 but missing in Debian Bookworm (e.g., eza, sd, git-delta, gping, yq, hyperfine) will be installed where available and skipped with warnings where not.
Expand Down Expand Up @@ -145,6 +157,7 @@ Scripts use category-based numeric prefixes with gaps for future expansion:
| `run_onchange_13-install-packages-apt.sh.tmpl` | Debian/Ubuntu packages via apt |
| `run_onchange_14-install-packages-dnf.sh.tmpl` | Fedora packages via dnf |
| `run_onchange_15-install-packages-rpm-ostree.sh.tmpl` | Immutable Fedora packages via rpm-ostree |
| `run_onchange_16-install-packages-mise.sh.tmpl` | mise packages at lockfile-pinned versions; installs a pinned mise via mise.run; links `~/.local/bin/fish` |
| `run_onchange_20-configure-pacman-repos.sh.tmpl` | Splices `~/.config/pacman/custom-repos-{head,tail}.conf` into `/etc/pacman.conf` via the omarchy `pre-refresh-pacman` hook (one sudo); omarchy-only |
| `run_onchange_30-install-packages-flatpak.sh.tmpl` | Flatpak GUI apps (Linux, tier 4+) |
| `run_onchange_31-install-packages-appimage.sh.tmpl` | AppImage downloads (Linux, last resort) |
Expand Down
Loading
Loading