Skip to content
Closed
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
6 changes: 4 additions & 2 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ version: 2
updates:
- package-ecosystem: "github-actions"
directory: "/"
labels: []
schedule:
interval: "daily"
groups:
Expand All @@ -12,7 +11,6 @@ updates:
update-types:
- "minor"
- "patch"
open-pull-requests-limit: 10
- package-ecosystem: "gitsubmodule"
directory: "/"
schedule:
Expand All @@ -37,6 +35,8 @@ updates:
update-types:
- "minor"
- "patch"
allow:
- dependency-type: "all"
- package-ecosystem: "uv"
directory: "/"
schedule:
Expand All @@ -50,6 +50,8 @@ updates:
update-types:
- "minor"
- "patch"
allow:
- dependency-type: "all"
- package-ecosystem: "npm"
directory: "/"
schedule:
Expand Down
44 changes: 31 additions & 13 deletions Home/.config/yadm/bootstrap
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,11 @@ install_base_deps(){
local pac_cmd="sudo pacman"
has paru && pac_cmd="paru"
has yay && pac_cmd="yay"
$pac_cmd -Sq --needed --noconfirm git gitoxide aria2 curl zsh fd sd ripgrep bat jq zoxide starship fzf stow tuckr rsync konsave || warn "Some packages may have failed to install"
# Try tuckr first, fall back to stow if unavailable
if ! $pac_cmd -Sq --needed --noconfirm git gitoxide aria2 curl zsh fd sd ripgrep bat jq zoxide starship fzf tuckr rsync konsave; then
warn "tuckr install failed, installing stow as fallback"
$pac_cmd -Sq --needed --noconfirm git gitoxide aria2 curl zsh fd sd ripgrep bat jq zoxide starship fzf stow rsync konsave || warn "Some packages may have failed to install"
fi
elif has apt-get; then
sudo apt-get update -y
sudo apt-get install -y git curl zsh fd-find ripgrep bat jq fzf stow rsync || warn "Some packages may have failed"
Expand Down Expand Up @@ -64,20 +68,34 @@ configure_shell(){
fi
}
deploy_system_configs(){
if ! has tuckr; then
warn "tuckr not installed; skipping etc/usr."
warn "Install tuckr then run: sudo tuckr link -d $REPO_DIR -t / etc usr"
local pkg use_tuckr=true

Copilot AI Dec 29, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The variable use_tuckr=true is declared but never used in the function. This unused variable should be removed to keep the code clean.

Suggested change
local pkg use_tuckr=true
local pkg

Copilot uses AI. Check for mistakes.
if has tuckr; then
info "Using tuckr for system config deployment"
local hooks_file="${REPO_DIR}/hooks.toml"
for pkg in etc usr; do
local src="${REPO_DIR}/${pkg}"
[[ -d $src ]] || { warn "Missing dir: $src"; continue; }
info "Linking ${pkg}/ → / (tuckr)"
local cmd=(sudo tuckr link -d "$REPO_DIR" -t / "$pkg")
[[ -f $hooks_file ]] && cmd+=(-H "$hooks_file")
"${cmd[@]}" || warn "Failed to link $pkg"
done
elif has stow; then
info "tuckr not found, using stow as fallback"
for pkg in etc usr; do
local src="${REPO_DIR}/${pkg}"
[[ -d $src ]] || { warn "Missing dir: $src"; continue; }
info "Linking ${pkg}/ → / (stow)"
(cd "$REPO_DIR" && sudo stow -t / -d . "$pkg") || warn "Failed to stow $pkg"
done
else
warn "Neither tuckr nor stow installed; skipping etc/usr deployment."
warn "Install tuckr: paru -S tuckr"
warn " OR stow: paru -S stow"
warn "Then run: sudo tuckr link -d $REPO_DIR -t / etc usr"
warn " OR: cd $REPO_DIR && sudo stow -t / etc usr"
return 0
fi
local hooks_file="${REPO_DIR}/hooks.toml" pkg
for pkg in etc usr; do
local src="${REPO_DIR}/${pkg}"
[[ -d $src ]] || { warn "Missing dir: $src"; continue; }
info "Linking ${pkg}/ → /"
local cmd=(sudo tuckr link -d "$REPO_DIR" -t / "$pkg")
[[ -f $hooks_file ]] && cmd+=(-H "$hooks_file")
"${cmd[@]}" || warn "Failed to link $pkg"
done
}
setup_alternates(){
info "Processing yadm alternates..."
Expand Down
114 changes: 114 additions & 0 deletions Home/.local/bin/deploy-system-configs.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
#!/usr/bin/env bash
# shellcheck enable=all shell=bash source-path=SCRIPTDIR
set -euo pipefail; shopt -s nullglob globstar
export LC_ALL=C; IFS=$'\n\t'
has(){ command -v -- "$1" &>/dev/null; }
info(){ printf '==> %s\n' "$*"; }
warn(){ printf '==> WARNING: %s\n' "$*"; }
die(){ printf '==> ERROR: %s\n' "$*" >&2; exit 1; }

# Get repository directory
get_repo_dir(){
if yadm rev-parse --show-toplevel &>/dev/null; then
yadm rev-parse --show-toplevel
elif [[ -d "${HOME}/.local/share/yadm/repo.git" ]]; then
echo "${HOME}"
elif git rev-parse --show-toplevel &>/dev/null; then
git rev-parse --show-toplevel
else
die "Cannot determine repository location"
fi
}

usage(){
cat <<'EOF'
deploy-system-configs - Deploy system configs using tuckr or stow

Usage: deploy-system-configs [OPTIONS] [PACKAGES...]

Options:
-h, --help Show this help
-d, --dir DIR Repository directory (auto-detected if omitted)
-u, --unlink Unlink/unstow packages instead of linking

Packages:
etc Deploy /etc configs
usr Deploy /usr configs
(default: etc usr)

This script automatically uses tuckr if available, otherwise falls back to stow.

Examples:
sudo deploy-system-configs # Deploy both etc and usr
sudo deploy-system-configs etc # Deploy only etc
sudo deploy-system-configs --unlink # Unlink all packages
EOF
}

REPO_DIR=""
UNLINK=false
PACKAGES=()

while [[ $# -gt 0 ]]; do
case "$1" in
-h|--help) usage; exit 0 ;;
-d|--dir)
if [[ -z ${2:-} ]]; then die "Option '$1' requires an argument."; fi
REPO_DIR="$2"; shift
;;
-u|--unlink) UNLINK=true ;;
-*) die "Unknown option: $1" ;;
*) PACKAGES+=("$1") ;;
esac
shift
done

# Auto-detect repo dir if not provided
[[ -z $REPO_DIR ]] && REPO_DIR="$(get_repo_dir)"
[[ -d $REPO_DIR ]] || die "Repository not found: $REPO_DIR"

# Default to etc and usr if no packages specified
((${#PACKAGES[@]} == 0)) && PACKAGES=(etc usr)

# Check if running as root
[[ $EUID -eq 0 ]] || die "This script must be run as root (use sudo)"

# Deploy using tuckr or stow
if has tuckr; then
info "Using tuckr for deployment"
local hooks_file="${REPO_DIR}/hooks.toml"

Copilot AI Dec 29, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The local keyword is being used outside of a function scope. In bash, local is only valid within functions. At the top level of a script, these should be regular variable declarations without the local keyword. This will cause the script to fail when executed.

Copilot uses AI. Check for mistakes.
for pkg in "${PACKAGES[@]}"; do
local src="${REPO_DIR}/${pkg}"

Copilot AI Dec 29, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The local keyword is being used outside of a function scope. In bash, local is only valid within functions. This should be a regular variable declaration without the local keyword.

Copilot uses AI. Check for mistakes.
[[ -d $src ]] || { warn "Directory not found: $src"; continue; }

if [[ $UNLINK == true ]]; then
info "Unlinking ${pkg}/"
tuckr unlink -d "$REPO_DIR" -t / "$pkg" || warn "Failed to unlink $pkg"
else
info "Linking ${pkg}/ → / (tuckr)"
local cmd=(tuckr link -d "$REPO_DIR" -t / "$pkg")

Copilot AI Dec 29, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The local keyword is being used outside of a function scope. In bash, local is only valid within functions. This should be a regular variable declaration without the local keyword.

Copilot uses AI. Check for mistakes.
[[ -f $hooks_file ]] && cmd+=(-H "$hooks_file")
"${cmd[@]}" || warn "Failed to link $pkg"
fi
done
elif has stow; then
info "Using stow for deployment (tuckr not available)"
for pkg in "${PACKAGES[@]}"; do
local src="${REPO_DIR}/${pkg}"

Copilot AI Dec 29, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The local keyword is being used outside of a function scope. In bash, local is only valid within functions. This should be a regular variable declaration without the local keyword.

Copilot uses AI. Check for mistakes.
[[ -d $src ]] || { warn "Directory not found: $src"; continue; }

if [[ $UNLINK == true ]]; then
info "Unstowing ${pkg}/"
(cd "$REPO_DIR" && stow -t / -d . -D "$pkg") || warn "Failed to unstow $pkg"
else
info "Stowing ${pkg}/ → / (stow)"
(cd "$REPO_DIR" && stow -t / -d . "$pkg") || warn "Failed to stow $pkg"
fi
done
else
die "Neither tuckr nor stow is installed. Install one of them:
Arch: paru -S tuckr OR paru -S stow
Debian: apt install stow"
fi

info "Deployment complete"
50 changes: 39 additions & 11 deletions YADM.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ clean, hierarchical folder structure.
```
dotfiles/
├── Home/ # User-level dotfiles (~/.*) [Managed by yadm]
├── etc/ # System configs (/etc/*) [Managed by tuckr]
├── usr/ # System configs (/usr/*) [Managed by tuckr]
├── etc/ # System configs (/etc/*) [Managed by tuckr/stow]
├── usr/ # System configs (/usr/*) [Managed by tuckr/stow]
├── .yadm/ # YADM configuration
│ ├── bootstrap # Main bootstrap script
│ └── config # Repository-wide yadm config
Expand All @@ -20,9 +20,10 @@ dotfiles/

- **Separation of concerns**: User configs vs. system configs
- **Easy to understand**: Mirrors Linux filesystem structure
- **Flexible deployment**: yadm for user files, tuckr for system files
- **Flexible deployment**: yadm for user files, tuckr/stow for system files
- **Git-friendly**: Clean repository with minimal clutter
- **Portable**: Works across different systems
- **Fallback support**: Automatically uses stow if tuckr is unavailable

---

Expand Down Expand Up @@ -169,7 +170,7 @@ yadm push

### Update System Configs (etc/, usr/)

System configs are managed separately with **tuckr**:
System configs are managed separately with **tuckr** (or **stow** as fallback):

```bash
# Navigate to repository
Expand All @@ -184,8 +185,14 @@ git commit -m "Update pacman configuration"
git push

# Re-link system configs (creates symlinks)
sudo tuckr link -d $(yadm rev-parse --show-toplevel) -t / etc
sudo tuckr link -d $(yadm rev-parse --show-toplevel) -t / usr
# Option 1: Using tuckr (preferred)
sudo tuckr link -d $(yadm rev-parse --show-toplevel) -t / etc usr

# Option 2: Using stow (fallback)
cd $(yadm rev-parse --show-toplevel) && sudo stow -t / etc usr

Copilot AI Dec 29, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The command sudo stow -t / etc usr at line 192 is incorrect. The stow syntax requires the -d option to specify the source directory when not already in that directory. The correct command would be: cd $(yadm rev-parse --show-toplevel) && sudo stow -t / -d . etc usr or simply cd $(yadm rev-parse --show-toplevel) && sudo stow -t / etc usr (since -d . is the default when in the directory). This matches the pattern used elsewhere in the code.

Suggested change
cd $(yadm rev-parse --show-toplevel) && sudo stow -t / etc usr
cd $(yadm rev-parse --show-toplevel) && sudo stow -t / -d . etc usr

Copilot uses AI. Check for mistakes.

# Option 3: Using helper script (auto-detects tuckr/stow)
sudo deploy-system-configs

Copilot AI Dec 29, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The command examples show inconsistent usage. Line 189 shows etc usr as separate arguments, line 192 also shows etc usr as separate arguments, but line 195 shows sudo deploy-system-configs without arguments (which would default to both). For consistency and clarity, all examples should explicitly show the arguments when demonstrating multi-package deployment: sudo deploy-system-configs etc usr.

Suggested change
sudo deploy-system-configs
sudo deploy-system-configs etc usr

Copilot uses AI. Check for mistakes.

Copilot AI Dec 29, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The documentation refers to the script as deploy-system-configs (lines 195, 280, 403) but the actual filename is deploy-system-configs.sh. Users would need to type deploy-system-configs.sh to execute it unless a symlink or alias without the .sh extension is created. Consider either: (1) renaming the file to remove the .sh extension to match the documentation, or (2) updating the documentation to include the .sh extension in all command examples.

Suggested change
sudo deploy-system-configs
sudo deploy-system-configs.sh

Copilot uses AI. Check for mistakes.
```

### Check Repository Status
Expand Down Expand Up @@ -256,15 +263,25 @@ Unlike traditional yadm setups where dotfiles are at the repository root, this r

The `.yadm/bootstrap` script handles this deployment automatically using rsync.

### System Configs with Tuckr
### System Configs with Tuckr or Stow

System-level configs (`/etc`, `/usr`) require root permissions and are managed with **tuckr**:
System-level configs (`/etc`, `/usr`) require root permissions and are managed with **tuckr** or **stow**:

```bash
# Using tuckr (preferred - supports hooks)
sudo tuckr link -d /path/to/repo -t / etc
# Creates: /etc/pacman.conf → /path/to/repo/etc/pacman.conf

# Using stow (fallback - widely available)
cd /path/to/repo && sudo stow -t / etc
# Creates: /etc/pacman.conf → /path/to/repo/etc/pacman.conf

# Using helper script (auto-detects best tool)
sudo deploy-system-configs etc usr
```

The bootstrap script automatically detects which tool is available and uses it accordingly.

---

## 🔧 Advanced Usage
Expand Down Expand Up @@ -366,13 +383,24 @@ echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.bashrc
### System configs not applying

```bash
# Install tuckr
# Option 1: Install tuckr (preferred)
paru -S tuckr # Arch/AUR

# Option 2: Install stow (fallback, widely available)
paru -S stow # Arch
sudo apt install stow # Debian/Ubuntu

# Re-link system configs with sudo
cd $(yadm rev-parse --show-toplevel)
sudo tuckr link -d "$PWD" -t / etc
sudo tuckr link -d "$PWD" -t / usr

# Using tuckr:
sudo tuckr link -d "$PWD" -t / etc usr

# OR using stow:
sudo stow -t / etc usr

Copilot AI Dec 29, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The command sudo stow -t / etc usr at line 400 is incorrect. The stow syntax requires being in the repository directory or specifying it with -d. The correct command would be: sudo stow -t / -d . etc usr (when already in the repo directory) or the cd command should be shown first like in line 395: cd "$PWD" && sudo stow -t / etc usr.

Suggested change
sudo stow -t / etc usr
sudo stow -t / -d "$PWD" etc usr

Copilot uses AI. Check for mistakes.

# OR using helper script (auto-detects):
sudo deploy-system-configs
```

---
Expand Down
50 changes: 35 additions & 15 deletions setup.sh
Original file line number Diff line number Diff line change
Expand Up @@ -48,15 +48,19 @@ main(){
install_packages(){
info "Installing packages..."
local paru_opts=(--needed --noconfirm --skipreview --sudoloop --batchinstall --combinedupgrade)
local pkgs=(git gitoxide aria2 curl zsh fd sd ripgrep bat jq zoxide starship fzf yadm tuckr konsave)
local pkgs=(git gitoxide aria2 curl zsh fd sd ripgrep bat jq zoxide starship fzf yadm konsave)
if ! has paru; then
die "paru not found."
fi
if [[ $DRY_RUN == true ]]; then
info "[DRY-RUN] Would install: ${pkgs[*]}"
info "[DRY-RUN] Would install: ${pkgs[*]} tuckr (or stow)"
return 0
fi
paru -Syuq "${paru_opts[@]}" "${pkgs[@]}" || die "Failed to install packages"
# Try installing with tuckr first
if ! paru -Syuq "${paru_opts[@]}" "${pkgs[@]}" tuckr; then
warn "tuckr install failed, using stow as fallback"
paru -Syuq "${paru_opts[@]}" "${pkgs[@]}" stow || die "Failed to install packages"
fi
}
setup_dotfiles(){
if ! has yadm; then
Expand All @@ -83,23 +87,39 @@ deploy_home(){
fi
}
link_system_configs(){
if ! has tuckr; then
warn "tuckr not found; skipping etc/usr deploy"
local pkg
if has tuckr; then
info "Using tuckr for system config deployment"
local hooks_file="${WORKTREE}/hooks.toml"
for pkg in etc usr; do
local src="${WORKTREE}/${pkg}"
[[ -d $src ]] || { warn "Directory not found: $src"; continue; }
info "Linking ${pkg}/ → / (tuckr)"
local cmd=(sudo tuckr link -d "$WORKTREE" -t / "$pkg")
[[ -f $hooks_file ]] && cmd+=(-H "$hooks_file")
"${cmd[@]}" || warn "Failed to link ${pkg}"
done
elif has stow; then
info "tuckr not found, using stow as fallback"
for pkg in etc usr; do
local src="${WORKTREE}/${pkg}"
[[ -d $src ]] || { warn "Directory not found: $src"; continue; }
info "Linking ${pkg}/ → / (stow)"
(cd "$WORKTREE" && sudo stow -t / -d . "$pkg") || warn "Failed to stow ${pkg}"
done
else
warn "Neither tuckr nor stow found; skipping etc/usr deploy"
warn "Install with: paru -S tuckr OR paru -S stow"
return 0
fi
local hooks_file="${WORKTREE}/hooks.toml" pkg
for pkg in etc usr; do
local src="${WORKTREE}/${pkg}"
[[ -d $src ]] || { warn "Directory not found: $src"; continue; }
info "Linking ${pkg}/ → /"
local cmd=(sudo tuckr link -d "$WORKTREE" -t / "$pkg")
[[ -f $hooks_file ]] && cmd+=(-H "$hooks_file")
"${cmd[@]}" || warn "Failed to link ${pkg}"
done
}
Comment on lines 89 to 115

Copilot AI Dec 29, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The system config deployment logic is duplicated across three files: setup.sh (lines 89-115), Home/.config/yadm/bootstrap (lines 70-99), and Home/.local/bin/deploy-system-configs.sh (lines 77-112). This duplication makes maintenance harder and increases the risk of inconsistencies. Consider extracting this logic into a shared function or having the other scripts call the deploy-system-configs.sh helper script instead of reimplementing the same logic.

Copilot uses AI. Check for mistakes.
final_steps(){
info "Run 'yadm status' to review."
info "For system configs: sudo tuckr link -d $WORKTREE -t / etc usr"
if has tuckr; then
info "For system configs: sudo tuckr link -d $WORKTREE -t / etc usr"
elif has stow; then
info "For system configs: cd $WORKTREE && sudo stow -t / etc usr"
fi
info "Validate /etc/fstab with: sudo systemd-analyze verify /etc/fstab"
info "Setup complete."
}
Expand Down
1 change: 1 addition & 0 deletions usr/.gitkeep
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# This directory is managed by tuckr and deployed to /usr
Loading
Loading