Link the agent half of user/ on the Mac mini
Manifest lines can now name an OS. The SSH config, pwswitch and espanso are Linux only, so link-user on the Mac links CLAUDE.md, rules, skills and the opencode commands and nothing else. link-mcp no longer aborts under the Mac's bash 3.2 when a server has no token.
This commit is contained in:
1 parent
27e28b0dd1
commit
d5ef335d61
5 files changed
+33
-9
No files matched your search
@@ -157,14 +157,17 @@ while read -r name transport target token_var _rest; do
|
|||||||
continue
|
continue
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# ${args[@]+...} rather than "${args[@]}": the Mac's bash 3.2 treats an
|
||||||
|
# empty array as unset under set -u and aborts the whole stage.
|
||||||
|
#
|
||||||
# Re-registering is how a new server or a rotated token reaches the
|
# Re-registering is how a new server or a rotated token reaches the
|
||||||
# runtime. Removing first avoids the CLI refusing a name it already knows.
|
# runtime. Removing first avoids the CLI refusing a name it already knows.
|
||||||
# Neither call may print the token, so both are quiet unless they fail.
|
# Neither call may print the token, so both are quiet unless they fail.
|
||||||
claude mcp remove "$name" -s user >/dev/null 2>&1 || true
|
claude mcp remove "$name" -s user >/dev/null 2>&1 || true
|
||||||
if [[ "$transport" == stdio ]]; then
|
if [[ "$transport" == stdio ]]; then
|
||||||
add=(claude mcp add "$name" -s user "${args[@]}" -- "$launcher")
|
add=(claude mcp add "$name" -s user ${args[@]+"${args[@]}"} -- "$launcher")
|
||||||
else
|
else
|
||||||
add=(claude mcp add --transport "$transport" "$name" "$url" "${args[@]}" -s user)
|
add=(claude mcp add --transport "$transport" "$name" "$url" ${args[@]+"${args[@]}"} -s user)
|
||||||
fi
|
fi
|
||||||
if "${add[@]}" >/dev/null 2>&1; then
|
if "${add[@]}" >/dev/null 2>&1; then
|
||||||
log "Registered $name."
|
log "Registered $name."
|
||||||
|
|||||||
@@ -69,10 +69,12 @@ displace() {
|
|||||||
|
|
||||||
linked=0
|
linked=0
|
||||||
copied=0
|
copied=0
|
||||||
|
os="$(uname -s | tr '[:upper:]' '[:lower:]')"
|
||||||
|
|
||||||
while read -r kind source destination; do
|
while read -r kind source destination only_on _rest; do
|
||||||
[[ -n "${kind:-}" ]] || continue
|
[[ -n "${kind:-}" ]] || continue
|
||||||
[[ "$kind" == \#* ]] && continue
|
[[ "$kind" == \#* ]] && continue
|
||||||
|
[[ -z "${only_on:-}" || "$only_on" == "$os" ]] || continue
|
||||||
|
|
||||||
src="$USER_DIR/$source"
|
src="$USER_DIR/$source"
|
||||||
dst="${destination/#\~/$HOME}"
|
dst="${destination/#\~/$HOME}"
|
||||||
|
|||||||
@@ -46,13 +46,15 @@ done < <(find "$repo_dir/user" -type f \( -name 'id_*' -o -name '*.pem' -o -name
|
|||||||
|
|
||||||
# ── Every manifest line is usable ───────────────────────────────────────────
|
# ── Every manifest line is usable ───────────────────────────────────────────
|
||||||
|
|
||||||
while read -r kind source destination; do
|
while read -r kind source destination only_on; do
|
||||||
[[ -e "$repo_dir/user/$source" ]] \
|
[[ -e "$repo_dir/user/$source" ]] \
|
||||||
|| note "the manifest points at $source, which is not in user/"
|
|| note "the manifest points at $source, which is not in user/"
|
||||||
[[ "$kind" == link || "$kind" == linkdir || "$kind" == copy ]] \
|
[[ "$kind" == link || "$kind" == linkdir || "$kind" == copy ]] \
|
||||||
|| note "the manifest uses an unknown kind: $kind"
|
|| note "the manifest uses an unknown kind: $kind"
|
||||||
[[ "$destination" == '~/'* ]] \
|
[[ "$destination" == '~/'* ]] \
|
||||||
|| note "the manifest destination $destination is not under the home directory"
|
|| note "the manifest destination $destination is not under the home directory"
|
||||||
|
[[ -z "$only_on" || "$only_on" == linux || "$only_on" == darwin ]] \
|
||||||
|
|| note "the manifest names an unknown os: $only_on"
|
||||||
done < <(grep -vE '^\s*(#|$)' "$manifest")
|
done < <(grep -vE '^\s*(#|$)' "$manifest")
|
||||||
|
|
||||||
# ── The behaviour, against a fake home ──────────────────────────────────────
|
# ── The behaviour, against a fake home ──────────────────────────────────────
|
||||||
@@ -77,6 +79,7 @@ linkdir agents/skills ~/.agents/skills
|
|||||||
linkdir agents/skills ~/.claude/skills
|
linkdir agents/skills ~/.claude/skills
|
||||||
copy plain.txt ~/.config/plain.txt
|
copy plain.txt ~/.config/plain.txt
|
||||||
link missing.txt ~/.config/missing.txt
|
link missing.txt ~/.config/missing.txt
|
||||||
|
copy plain.txt ~/.config/elsewhere.txt nosuchos
|
||||||
FIXTURE
|
FIXTURE
|
||||||
|
|
||||||
home="$work/home"
|
home="$work/home"
|
||||||
@@ -141,6 +144,11 @@ fi
|
|||||||
grep -q 'missing.txt' "$work/log" \
|
grep -q 'missing.txt' "$work/log" \
|
||||||
|| note 'a skipped manifest entry was not reported'
|
|| note 'a skipped manifest entry was not reported'
|
||||||
|
|
||||||
|
# A line naming another OS is for another machine. The Mac takes the agent half
|
||||||
|
# of user/ and none of the Linux desktop half.
|
||||||
|
[[ -e "$home/.config/elsewhere.txt" ]] \
|
||||||
|
&& note 'a manifest entry for another OS was applied here'
|
||||||
|
|
||||||
# ── The answer sticks ───────────────────────────────────────────────────────
|
# ── The answer sticks ───────────────────────────────────────────────────────
|
||||||
#
|
#
|
||||||
# So that `panama upgrade` on a configured machine relinks without an interview,
|
# So that `panama upgrade` on a configured machine relinks without an interview,
|
||||||
|
|||||||
@@ -86,6 +86,12 @@ Put the file under `user/`, add a line to `manifest`, run:
|
|||||||
Anything already at the destination is moved to `config/old/` rather than
|
Anything already at the destination is moved to `config/old/` rather than
|
||||||
deleted, under a name that says where it came from.
|
deleted, under a name that says where it came from.
|
||||||
|
|
||||||
|
A line can end with `linux` or `darwin` to apply only on that OS. The Mac mini
|
||||||
|
is not a Panama desktop, but it runs agents, so it takes the agent half of this
|
||||||
|
directory and skips the SSH config, `pwswitch` and espanso. Panama's shipped
|
||||||
|
skills describe the Linux desktop, so the Mac runs `link-user` and `link-mcp`
|
||||||
|
only, never `link-skills`.
|
||||||
|
|
||||||
## What does not go in here
|
## What does not go in here
|
||||||
|
|
||||||
Anything secret. This repository is readable by anyone who finds it, and the
|
Anything secret. This repository is readable by anyone who finds it, and the
|
||||||
|
|||||||
+10
-5
@@ -1,6 +1,6 @@
|
|||||||
# What in user/ goes where, and in what form.
|
# What in user/ goes where, and in what form.
|
||||||
#
|
#
|
||||||
# <kind> <source under user/> <destination>
|
# <kind> <source under user/> <destination> [os]
|
||||||
#
|
#
|
||||||
# kind is one of:
|
# kind is one of:
|
||||||
# link symlink the destination at the source, so editing either edits the
|
# link symlink the destination at the source, so editing either edits the
|
||||||
@@ -14,6 +14,10 @@
|
|||||||
# copy copy once, and never touch it again if the destination exists. Use
|
# copy copy once, and never touch it again if the destination exists. Use
|
||||||
# this for files a machine legitimately diverges on.
|
# this for files a machine legitimately diverges on.
|
||||||
#
|
#
|
||||||
|
# os is optional: linux or darwin, matched against `uname -s`. A line naming
|
||||||
|
# one is skipped everywhere else. Leave it off for anything every machine
|
||||||
|
# wants, which is most of this file; the Mac mini only takes the agent half.
|
||||||
|
#
|
||||||
# Lines beginning with # are comments and blank lines are ignored. ~ in a
|
# Lines beginning with # are comments and blank lines are ignored. ~ in a
|
||||||
# destination is this user's home.
|
# destination is this user's home.
|
||||||
#
|
#
|
||||||
@@ -43,21 +47,22 @@ link agents/rules ~/.claude/rules
|
|||||||
# ── SSH ──────────────────────────────────────────────────────────────────────
|
# ── SSH ──────────────────────────────────────────────────────────────────────
|
||||||
# Host aliases only. Keys are per-machine and are never tracked; this is the
|
# Host aliases only. Keys are per-machine and are never tracked; this is the
|
||||||
# file that makes `ssh server` work the moment a machine is set up, and it is
|
# file that makes `ssh server` work the moment a machine is set up, and it is
|
||||||
# what the SSH Hosts launcher command reads.
|
# what the SSH Hosts launcher command reads. Linux only: it names id_ed25519
|
||||||
link ssh/config ~/.ssh/config
|
# and the desktop keyring's agent socket, and the Mac has neither.
|
||||||
|
link ssh/config ~/.ssh/config linux
|
||||||
|
|
||||||
# ── Scripts ──────────────────────────────────────────────────────────────────
|
# ── Scripts ──────────────────────────────────────────────────────────────────
|
||||||
# Personal commands wanted on every machine, desktop or server. ~/.local/bin is
|
# Personal commands wanted on every machine, desktop or server. ~/.local/bin is
|
||||||
# on PATH in both shell configs. pwswitch toggles passwordless sudo through a
|
# on PATH in both shell configs. pwswitch toggles passwordless sudo through a
|
||||||
# sudoers.d drop-in, so an agent can run sudo and the password comes back after.
|
# sudoers.d drop-in, so an agent can run sudo and the password comes back after.
|
||||||
link bin/pwswitch ~/.local/bin/pwswitch
|
link bin/pwswitch ~/.local/bin/pwswitch linux
|
||||||
|
|
||||||
# ── Espanso ──────────────────────────────────────────────────────────────────
|
# ── Espanso ──────────────────────────────────────────────────────────────────
|
||||||
# The personal expansion triggers. Copied rather than linked, because this is a
|
# The personal expansion triggers. Copied rather than linked, because this is a
|
||||||
# file each machine may add its own triggers to. It lands before setup-identity
|
# file each machine may add its own triggers to. It lands before setup-identity
|
||||||
# runs, and that stage only seeds a file that does not exist yet, so what is
|
# runs, and that stage only seeds a file that does not exist yet, so what is
|
||||||
# tracked here wins over the name and email the interview would have written.
|
# tracked here wins over the name and email the interview would have written.
|
||||||
copy espanso/identity.yml ~/.config/espanso/match/identity.yml
|
copy espanso/identity.yml ~/.config/espanso/match/identity.yml linux
|
||||||
|
|
||||||
# ── OpenCode ─────────────────────────────────────────────────────────────────
|
# ── OpenCode ─────────────────────────────────────────────────────────────────
|
||||||
# Claude Code carries its commands and agents as plugins, which opencode cannot
|
# Claude Code carries its commands and agents as plugins, which opencode cannot
|
||||||
|
|||||||
Reference in new issue
Block a user