Repository navigation
refactor: extract all inline home.activation scripts to bash files #1443
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 1 commit
d891f73
484b173
92cee4f
8980fa8
f7b7738
bd4f90b
1144962
a2a71c0
53b9d51
41041d4
533f320
39ac87d
b626b35
044fce8
832420a
21dbf5a
860d305
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,9 @@ | ||
| #!/usr/bin/env bash | ||
| # Copy Claude settings.json (git-ai needs write access, breaks with symlinks) | ||
| # Usage: activate.sh <settings_json> | ||
| set -euo pipefail | ||
| SETTINGS_JSON="$1" | ||
|
|
||
| mkdir -p ~/.claude | ||
| cp -f "$SETTINGS_JSON" ~/.claude/settings.json | ||
| chmod 644 ~/.claude/settings.json |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,12 @@ | ||
| #!/usr/bin/env bash | ||
| # Copy Codex config files (atomic writes break symlinks) | ||
| # Usage: activate.sh <config_toml> <hooks_json> | ||
| set -euo pipefail | ||
| CONFIG_TOML="$1" | ||
| HOOKS_JSON="$2" | ||
|
|
||
| mkdir -p ~/.codex/hooks | ||
| cp -f "$CONFIG_TOML" ~/.codex/config.toml | ||
| chmod 600 ~/.codex/config.toml | ||
| cp -f "$HOOKS_JSON" ~/.codex/hooks.json | ||
| chmod 644 ~/.codex/hooks.json |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,9 @@ | ||
| #!/usr/bin/env bash | ||
| # Copy Cursor hooks.json (git-ai needs write access, breaks with symlinks) | ||
| # Usage: activate.sh <hooks_json> | ||
| set -euo pipefail | ||
| HOOKS_JSON="$1" | ||
|
|
||
| mkdir -p ~/.cursor | ||
| cp -f "$HOOKS_JSON" ~/.cursor/hooks.json | ||
| chmod 644 ~/.cursor/hooks.json |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,10 +1,8 @@ | ||
| { lib, ... }: | ||
| { lib, pkgs, ... }: | ||
| { | ||
| # Use activation script instead of symlink | ||
| # git-ai install-hooks needs write access, which breaks with Nix store symlinks | ||
| home.activation.cursorHooks = lib.hm.dag.entryAfter [ "writeBoundary" ] '' | ||
| $DRY_RUN_CMD mkdir -p ~/.cursor | ||
| $DRY_RUN_CMD cp -f ${./hooks.json} ~/.cursor/hooks.json | ||
| $DRY_RUN_CMD chmod 644 ~/.cursor/hooks.json | ||
| $DRY_RUN_CMD ${pkgs.bash}/bin/bash ${./activate.sh} ${./hooks.json} | ||
| ''; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,11 @@ | ||
| #!/usr/bin/env bash | ||
| # Copy Gemini settings.json if it doesn't already exist | ||
| # Usage: activate.sh <settings_json> | ||
| set -euo pipefail | ||
| SETTINGS_JSON="$1" | ||
|
|
||
| mkdir -p "$HOME/.gemini" | ||
| if [ ! -f "$HOME/.gemini/settings.json" ]; then | ||
| cp "$SETTINGS_JSON" "$HOME/.gemini/settings.json" | ||
| chmod 644 "$HOME/.gemini/settings.json" | ||
| fi |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,15 +1,8 @@ | ||
| { config, ... }: | ||
| let | ||
| geminiSettingsSource = ./settings.json; | ||
| in | ||
| { config, pkgs, ... }: | ||
| { | ||
| # Use activation script to copy settings.json instead of symlinking | ||
| # This allows ruler and other tools to modify the file | ||
| home.activation.geminiSettings = config.lib.dag.entryAfter [ "writeBoundary" ] '' | ||
| mkdir -p "$HOME/.gemini" | ||
| if [ ! -f "$HOME/.gemini/settings.json" ]; then | ||
| $DRY_RUN_CMD cp ${geminiSettingsSource} "$HOME/.gemini/settings.json" | ||
| $DRY_RUN_CMD chmod 644 "$HOME/.gemini/settings.json" | ||
| fi | ||
| $DRY_RUN_CMD ${pkgs.bash}/bin/bash ${./activate.sh} ${./settings.json} | ||
| ''; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,23 @@ | ||
| #!/usr/bin/env bash | ||
| # Sync k3s config to /etc/rancher/k3s/ (requires sudo) | ||
| set -euo pipefail | ||
|
|
||
| if [ ! -f "$HOME/.config/k3s/config.yaml" ]; then | ||
| exit 0 | ||
| fi | ||
|
|
||
| SUDO_CMD="" | ||
| if command -v sudo >/dev/null 2>&1; then | ||
| SUDO_CMD="sudo" | ||
| elif [ -x /run/wrappers/bin/sudo ]; then | ||
| SUDO_CMD="/run/wrappers/bin/sudo" | ||
| elif [ -x /usr/bin/sudo ]; then | ||
| SUDO_CMD="/usr/bin/sudo" | ||
| fi | ||
|
|
||
| if [ -n "$SUDO_CMD" ]; then | ||
| $SUDO_CMD mkdir -p /etc/rancher/k3s | ||
| $SUDO_CMD cp "$HOME/.config/k3s/config.yaml" /etc/rancher/k3s/config.yaml | ||
| else | ||
| echo "Warning: sudo not found, skipping k3s config installation" >&2 | ||
| fi | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,10 @@ | ||
| #!/usr/bin/env bash | ||
| # Copy OMP config and set up extension symlink | ||
| # Usage: activate.sh <config_yml> | ||
| set -euo pipefail | ||
| CONFIG_YML="$1" | ||
|
|
||
| mkdir -p ~/.omp/agent ~/.omp/agent/extensions | ||
| cp -f "$CONFIG_YML" ~/.omp/agent/config.yml | ||
| chmod 644 ~/.omp/agent/config.yml | ||
| ln -sfn "$HOME/dotfiles/node_modules/@oh-my-pi/swarm-extension" ~/.omp/agent/extensions/swarm-extension |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,11 +1,8 @@ | ||
| { lib, ... }: | ||
| { lib, pkgs, ... }: | ||
| { | ||
| # Use activation script instead of home.file symlink. | ||
| # Keep only the tracked config.yml in dotfiles and leave runtime state untouched. | ||
| home.activation.ompConfig = lib.hm.dag.entryAfter [ "writeBoundary" ] '' | ||
| $DRY_RUN_CMD mkdir -p ~/.omp/agent ~/.omp/agent/extensions | ||
| $DRY_RUN_CMD cp -f ${./config.yml} ~/.omp/agent/config.yml | ||
| $DRY_RUN_CMD chmod 644 ~/.omp/agent/config.yml | ||
| $DRY_RUN_CMD ln -sfn "$HOME/dotfiles/node_modules/@oh-my-pi/swarm-extension" ~/.omp/agent/extensions/swarm-extension | ||
| $DRY_RUN_CMD ${pkgs.bash}/bin/bash ${./activate.sh} ${./config.yml} | ||
| ''; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,13 @@ | ||
| #!/usr/bin/env bash | ||
| # Copy Serena config if missing or is a symlink | ||
| # Usage: activate.sh <source> <dest> | ||
| set -euo pipefail | ||
| SRC="$1" | ||
| DEST="$2" | ||
|
|
||
| mkdir -p "$(dirname "$DEST")" | ||
| if [ ! -f "$DEST" ] || [ -L "$DEST" ]; then | ||
| rm -f "$DEST" | ||
| cp "$SRC" "$DEST" | ||
| chmod u+w "$DEST" | ||
| fi |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,15 +1,9 @@ | ||
| { config, ... }: | ||
| { config, pkgs, ... }: | ||
| let | ||
| serenaConfigSrc = ./serena_config.yml; | ||
| serenaConfigDest = "${config.home.homeDirectory}/.serena/serena_config.yml"; | ||
| in | ||
| { | ||
| home.activation.serenaConfig = config.lib.dag.entryAfter [ "writeBoundary" ] '' | ||
| mkdir -p "$(dirname "${serenaConfigDest}")" | ||
| if [ ! -f "${serenaConfigDest}" ] || [ -L "${serenaConfigDest}" ]; then | ||
| rm -f "${serenaConfigDest}" | ||
| cp "${serenaConfigSrc}" "${serenaConfigDest}" | ||
| chmod u+w "${serenaConfigDest}" | ||
| fi | ||
| $DRY_RUN_CMD ${pkgs.bash}/bin/bash ${./activate.sh} ${./serena_config.yml} "${serenaConfigDest}" | ||
| ''; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,25 @@ | ||
| #!/usr/bin/env bash | ||
| # Decrypt and deploy an agenix secret if destination doesn't exist | ||
| # Usage: deploy-agenix-secret.sh <dest_path> <secret_file> <identity_key> <rage_bin> | ||
| set -euo pipefail | ||
| DEST="$1" | ||
| SECRET_FILE="$2" | ||
| IDENTITY_KEY="$3" | ||
| RAGE_BIN="$4" | ||
|
|
||
| if [[ -f "$DEST" ]]; then | ||
| exit 0 | ||
| fi | ||
|
|
||
| echo "Deploying secret from agenix..." | ||
| if [[ ! -f "$SECRET_FILE" ]]; then | ||
| echo "Warning: Secret file not found at $SECRET_FILE" >&2 | ||
| exit 0 | ||
| fi | ||
|
|
||
| if "$RAGE_BIN" -d -i "$IDENTITY_KEY" "$SECRET_FILE" -o "$DEST" 2>/dev/null; then | ||
| chmod 0600 "$DEST" | ||
| echo "Secret deployed successfully" | ||
| else | ||
| echo "Warning: SSH key not authorized to decrypt - skipping" >&2 | ||
| fi |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,9 @@ | ||
| #!/usr/bin/env bash | ||
| # Create directories with specified permissions | ||
| # Usage: ensure-directory.sh <mode> <dir1> [dir2...] | ||
| set -euo pipefail | ||
| MODE="$1"; shift | ||
| for DIR in "$@"; do | ||
| mkdir -p "$DIR" | ||
| chmod "$MODE" "$DIR" | ||
| done |
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,28 @@ | ||||||||||||||||||||||||||
| #!/usr/bin/env bash | ||||||||||||||||||||||||||
| # Import GPG key from agenix-encrypted file | ||||||||||||||||||||||||||
| # Usage: import-gpg-key.sh <gpg_secret_file> <identity_key> <agenix_dir> <rage_bin> <gpg_bin> <key_fingerprint> | ||||||||||||||||||||||||||
| set -euo pipefail | ||||||||||||||||||||||||||
| GPG_SECRET_FILE="$1" | ||||||||||||||||||||||||||
| IDENTITY_KEY="$2" | ||||||||||||||||||||||||||
| AGENIX_DIR="$3" | ||||||||||||||||||||||||||
| RAGE_BIN="$4" | ||||||||||||||||||||||||||
| GPG_BIN="$5" | ||||||||||||||||||||||||||
| KEY_FINGERPRINT="$6" | ||||||||||||||||||||||||||
| GPG_TEMP_FILE="$AGENIX_DIR/gpg.key" | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| mkdir -p "$AGENIX_DIR" | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| if [[ ! -f "$GPG_SECRET_FILE" ]]; then | ||||||||||||||||||||||||||
| exit 0 | ||||||||||||||||||||||||||
| fi | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| if "$GPG_BIN" --list-secret-keys 2>/dev/null | grep -q "$KEY_FINGERPRINT"; then | ||||||||||||||||||||||||||
| exit 0 | ||||||||||||||||||||||||||
| fi | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| echo "Importing GPG key from agenix..." | ||||||||||||||||||||||||||
| if "$RAGE_BIN" -d -i "$IDENTITY_KEY" -o "$GPG_TEMP_FILE" "$GPG_SECRET_FILE" 2>/dev/null; then | ||||||||||||||||||||||||||
| "$GPG_BIN" --batch --import "$GPG_TEMP_FILE" 2>/dev/null | ||||||||||||||||||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. P1: Ensure the decrypted temp key file is removed even when GPG import fails; with Prompt for AI agents |
||||||||||||||||||||||||||
| rm -f "$GPG_TEMP_FILE" | ||||||||||||||||||||||||||
| echo "GPG key imported successfully" | ||||||||||||||||||||||||||
| fi | ||||||||||||||||||||||||||
|
Comment on lines
+23
to
+28
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The decrypted GPG private key is written to a temporary file on disk. If the script is interrupted or if the
Suggested change
|
||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,38 @@ | ||
| #!/usr/bin/env bash | ||
| # Create /bin shell symlinks on non-NixOS Linux systems | ||
| # Usage: activate.sh <bash_path> <fish_path> <zsh_path> | ||
| set -euo pipefail | ||
| BASH_PATH="$1" | ||
| FISH_PATH="$2" | ||
| ZSH_PATH="$3" | ||
|
|
||
| # Skip on NixOS - /bin symlinks are managed at the system level | ||
| if [ -f /etc/NIXOS ]; then | ||
| echo "Skipping /bin shell symlinks on NixOS (managed by system configuration)" | ||
| exit 0 | ||
| fi | ||
|
|
||
| SUDO_CMD="" | ||
| if command -v sudo >/dev/null 2>&1; then | ||
| SUDO_CMD="sudo" | ||
| elif [ -x /run/wrappers/bin/sudo ]; then | ||
| SUDO_CMD="/run/wrappers/bin/sudo" | ||
| elif [ -x /usr/bin/sudo ]; then | ||
| SUDO_CMD="/usr/bin/sudo" | ||
| elif [ "$(id -u)" -ne 0 ]; then | ||
| echo "Creating /bin shell symlinks requires root privileges, but sudo is not available." >&2 | ||
| exit 1 | ||
| fi | ||
|
|
||
| run_root_cmd() { | ||
| if [ -n "$SUDO_CMD" ]; then | ||
| "$SUDO_CMD" "$@" | ||
| else | ||
| "$@" | ||
| fi | ||
| } | ||
|
|
||
| run_root_cmd mkdir -p /bin | ||
| run_root_cmd ln -sf "$BASH_PATH" /bin/bash | ||
| run_root_cmd ln -sf "$FISH_PATH" /bin/fish | ||
| run_root_cmd ln -sf "$ZSH_PATH" /bin/zsh | ||
|
Comment on lines
+36
to
+38
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Overwriting |
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The sudo detection logic is duplicated across multiple activation scripts (
k3s,bin-shells,tailscale,ip-forwarding). This logic should be refactored into a shared helper script inhome-manager/activation/to improve maintainability and ensure consistent behavior (e.g., consistent support fordoasand error handling).