Skip to content

Commit 6216231

Browse files
committed
sync helper for private skills
1 parent f89b305 commit 6216231

2 files changed

Lines changed: 88 additions & 0 deletions

File tree

install.conf.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
~/.local/bin/commit-count-per-month.py: scripts/commit-count-per-month.py
2828
~/.local/bin/maxminvers.py: scripts/maxminvers.py
2929
~/.local/bin/inotify-consumers: scripts/inotify-consumers
30+
~/.local/bin/dsync: scripts/dsync
3031
~/.local/bin/wa: scripts/wa
3132
~/.local/bin/zig: zig/zig
3233
~/.tmux.conf: tmux/.tmux.conf

scripts/dsync

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
#!/usr/bin/env bash
2+
# dsync - dotfiles sync
3+
#
4+
# - pulls dotfiles repo (if on main) and runs ./install
5+
# - pulls or sets up the private skills repo linked at ~/.claude/skills
6+
7+
set -uo pipefail
8+
9+
SKILLS_REPO_URL="git@github.com:noahp/noahp-private-skills.git"
10+
SKILLS_REPO_NAME="noahp-private-skills"
11+
12+
# Resolve the dotfiles repo root from this script's real location
13+
SCRIPT_REAL="$(readlink -f "${BASH_SOURCE[0]}")"
14+
DOTFILES_DIR="$(cd "$(dirname "$SCRIPT_REAL")/.." && pwd)"
15+
16+
info() { echo " $*"; }
17+
warn() { echo " [warn] $*"; }
18+
skip() { echo " [skip] $*"; }
19+
step() { echo "==> $*"; }
20+
21+
# Pull dotfiles repo and re-run install
22+
sync_dotfiles() {
23+
step "Syncing dotfiles ($DOTFILES_DIR)..."
24+
25+
local branch
26+
branch=$(git -C "$DOTFILES_DIR" branch --show-current 2>/dev/null)
27+
28+
if [[ "$branch" != "main" ]]; then
29+
skip "Not on main (on '$branch')"
30+
return
31+
fi
32+
33+
git -C "$DOTFILES_DIR" pull
34+
"$DOTFILES_DIR/install"
35+
}
36+
37+
# Pull or set up the private skills repo
38+
sync_skills() {
39+
step "Checking ~/.claude/skills..."
40+
41+
local skills_path="$HOME/.claude/skills"
42+
43+
# Case 1: symlink — find the git repo root and pull if on main
44+
if [[ -L "$skills_path" ]]; then
45+
local target git_root branch
46+
target="$(readlink -f "$skills_path")"
47+
git_root="$(git -C "$target" rev-parse --show-toplevel 2>/dev/null || true)"
48+
49+
if [[ -z "$git_root" ]]; then
50+
warn "~/.claude/skills is a symlink but not inside a git repo, skipping"
51+
return
52+
fi
53+
54+
branch=$(git -C "$git_root" branch --show-current 2>/dev/null)
55+
if [[ "$branch" != "main" ]]; then
56+
skip "Skills repo not on main (on '$branch')"
57+
return
58+
fi
59+
60+
info "Pulling skills repo ($git_root)..."
61+
git -C "$git_root" pull
62+
return
63+
fi
64+
65+
# Case 2: doesn't exist or is empty — clone and symlink
66+
if [[ ! -e "$skills_path" ]] || [[ -z "$(ls -A "$skills_path" 2>/dev/null)" ]]; then
67+
local skills_repo_dir
68+
skills_repo_dir="$(cd "$DOTFILES_DIR/.." && pwd)/$SKILLS_REPO_NAME"
69+
70+
if [[ ! -d "$skills_repo_dir" ]]; then
71+
info "Cloning $SKILLS_REPO_URL -> $skills_repo_dir..."
72+
git clone "$SKILLS_REPO_URL" "$skills_repo_dir"
73+
fi
74+
75+
info "Symlinking ~/.claude/skills -> $skills_repo_dir/skills"
76+
[[ -e "$skills_path" ]] && rm -rf "$skills_path"
77+
ln -s "$skills_repo_dir/skills" "$skills_path"
78+
return
79+
fi
80+
81+
# Case 3: exists, not a symlink, not empty
82+
warn "~/.claude/skills exists and is not a symlink — not touching it"
83+
}
84+
85+
sync_dotfiles
86+
sync_skills
87+
step "Done."

0 commit comments

Comments
 (0)