81 lines
2.9 KiB
Bash
Executable File
81 lines
2.9 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
|
|
# Agent skills, shipped to every machine.
|
|
#
|
|
# Panama is a desktop that an agent is frequently asked to operate: open the
|
|
# settings, check what is running, take a screenshot, run something as root. An
|
|
# agent that has to infer all of that from the source reliably invents half of
|
|
# it, so the machine carries its own manual and skills/ is where it lives.
|
|
#
|
|
# This stage is un-gated, unlike link-user. What it links is documentation of
|
|
# this repository, not anybody's personal content, so a stranger who clones
|
|
# Panama wants it for exactly the same reason its author does.
|
|
#
|
|
# ~/.agents/skills and ~/.claude/skills may each start as a single symlink into
|
|
# user/agents/skills, but a directory cannot point at personal and shipped
|
|
# skills at once. Both destinations become real directories with one link per
|
|
# skill. link-user runs after this stage on purpose, so a personal skill named
|
|
# like a shipped one wins in every agent runtime.
|
|
|
|
set -euo pipefail
|
|
|
|
log() { echo -e "\033[1;34m[INFO]\033[0m $*"; }
|
|
|
|
PANAMA_PATH="${PANAMA_PATH:-$HOME/.local/share/Panama}"
|
|
SKILLS_DIR="$PANAMA_PATH/skills"
|
|
PANAMA_OLD="$PANAMA_PATH/config/old"
|
|
DESTINATIONS=("$HOME/.agents/skills" "$HOME/.claude/skills")
|
|
|
|
[[ -d "$SKILLS_DIR" ]] || { log "No skills/ in this checkout; nothing to link."; exit 0; }
|
|
|
|
mkdir -p "$PANAMA_OLD"
|
|
|
|
# Moves whatever is already at a destination out of the way, once -- the same
|
|
# promise link-dotfiles and link-user make. A symlink is removed rather than
|
|
# backed up: it is a pointer this installer made, and keeping copies of it
|
|
# would grow config/old/ by one entry on every upgrade.
|
|
displace() {
|
|
local destination="$1" backup
|
|
if [[ -L "$destination" ]]; then
|
|
rm -f "$destination"
|
|
return 0
|
|
fi
|
|
[[ -e "$destination" ]] || return 0
|
|
|
|
backup="$PANAMA_OLD/skills-$(printf '%s' "${destination#"$HOME"/}" | tr '/' '-')"
|
|
if [[ -e "$backup" ]]; then
|
|
backup="$backup.$(date +%s)"
|
|
fi
|
|
mv "$destination" "$backup"
|
|
log "Moved existing $destination to $backup"
|
|
}
|
|
|
|
# Each destination has to be a real directory before anything can be linked
|
|
# into it. An old whole-directory symlink is removed; a regular file somebody
|
|
# left at the path is kept in config/old/.
|
|
for destination in "${DESTINATIONS[@]}"; do
|
|
mkdir -p "$(dirname "$destination")"
|
|
if [[ -L "$destination" ]]; then
|
|
rm -f "$destination"
|
|
log "Removed the old $destination symlink; skills are linked one by one now"
|
|
elif [[ -e "$destination" && ! -d "$destination" ]]; then
|
|
displace "$destination"
|
|
fi
|
|
mkdir -p "$destination"
|
|
done
|
|
|
|
linked=0
|
|
for skill in "$SKILLS_DIR"/*; do
|
|
[[ -e "$skill" ]] || continue
|
|
name="$(basename "$skill")"
|
|
for destination in "${DESTINATIONS[@]}"; do
|
|
target="$destination/$name"
|
|
displace "$target"
|
|
ln -s "$skill" "$target"
|
|
log "Linked skills/$name → $target"
|
|
done
|
|
linked=$(( linked + 1 ))
|
|
done
|
|
|
|
log "Agent skills: $linked linked."
|